/* ===== TextPeek — the rest of a clamped paragraph, on demand =====

   Scene mode makes one promise: a section is a screen. Keeping it means some
   copy is longer than the box it has to live in, and five places on this page
   are clamped to a line count that varies with the viewport — the project
   blurbs, the three paragraphs of the bio, the brand notes beside each reel,
   and (in landscape only) the hero's second sentence and the service cards.

   The rest of that text has to be reachable, and it cannot be reached by
   expanding it in place: a paragraph that grows pushes its panel past the
   screen, which is the one thing the whole layout exists to prevent. So it
   opens OUT of the flow instead, in a panel that floats over the page and
   costs the layout nothing. Tap the text, it opens; tap again, or anywhere
   else, or press Escape, and it closes.

   Nothing here changes what is in the document. The clamp is visual only —
   `-webkit-line-clamp` hides lines from the eye and from nobody else, so the
   full text has always been there for search engines and screen readers. This
   is an affordance for people looking at it, which is why the floating panel
   is aria-hidden: it would otherwise read the same paragraph out twice. */

/* The clamped paragraph itself, once js/text-peek.js has found it actually
   overflowing. Applied by JS and not by the stylesheet, because whether a
   given paragraph is clamped depends on the viewport, and on a 1080p desktop
   most of these are not clamped at all and must stay plain text. */
.is-clamped {
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

/* The cue: the clamp's own ellipsis, in the accent, made into a button.

   It used to be a label sitting in the corner of the box — CONTINUA on a dark
   scrim, later just the mark on one — and either way it was laid OVER text
   that was still there underneath, however faint, which is what made it read
   as a patch stuck onto the paragraph rather than something the paragraph
   was doing on purpose.

   It no longer overlaps anything. js/text-peek.js trims the paragraph back
   word by word — never mid-word — until what is left plus this mark fits the
   box on their own; the cut always lands at a word boundary that leaves room.
   So the ellipsis is now real inline text, the last thing on the last line,
   with the space before it that a trailing "…" is supposed to have. Nothing
   below positions it: it sits exactly where normal text flow puts it. `all:
   unset` strips the browsers's own button chrome (padding, border, the
   inline-block box) down to nothing so what is left reads as a character,
   not a control, and then re-declares only cursor and colour. */
.text-peek-cue {
  all: unset;
  display: inline;
  cursor: pointer;
  color: var(--accent);
  -webkit-tap-highlight-color: transparent;
  transition: color 0.3s var(--ease);
}
.is-clamped:hover .text-peek-cue,
.text-peek-cue:focus-visible { color: #fff; }
.text-peek-cue:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; border-radius: 2px; }

/* Open: the same mark, lit, because tapping it again is what puts it away. */
.is-peeking .text-peek-cue { color: #fff; }

/* ===== The panel =====
   Fixed to the viewport and appended to <body>, which is what keeps it clear
   of everything the page does to its own boxes: the scene stage is fixed and
   its panels carry perspective transforms, .scene-inner clips on overflow,
   and the card rails clip on overflow-x. A child of any of those would be
   cut off or dragged along by a transform. A child of <body> is not.

   z-index sits above the navbar (100), the footer drawer (95) and the laser
   (94) — it is the frontmost thing on the page while it is open, because it
   is the only thing the reader just asked for. */
.text-peek {
  position: fixed;
  z-index: 200;
  --lg-radius: 20px;
  padding: 18px 20px;

  /* The glass material is tuned for a card sitting on the page's near-black,
     and this panel does not always get that: over #progetti and #chi-sono the
     LiquidEther field is drifting behind it, and the material's own
     saturate(210%) brightness(1.14) pulls that amber straight through the
     backdrop and lays it under the text. A card can afford that — it is
     decoration behind a heading. This cannot: it exists to be read, and it
     is the one thing on screen the reader explicitly asked for.

     So the body of the glass is opaque enough to guarantee the contrast, and
     the backdrop is left doing what is still worth doing — blurring what is
     behind into a soft ground rather than amplifying it. */
  background-color: rgba(9, 9, 10, 0.9);
  -webkit-backdrop-filter: blur(26px) saturate(120%);
          backdrop-filter: blur(26px) saturate(120%);
  max-width: calc(100vw - 24px);
  overflow-y: auto;
  overscroll-behavior: contain;
  /* The page underneath is pinned and reads every vertical drag as a page
     turn; inside here a drag has to scroll this and nothing else. */
  touch-action: pan-y;
  scrollbar-width: thin;

  opacity: 0;
  visibility: hidden;
  translate: 0 -6px;
  scale: 0.98;
  transform-origin: top left;
  transition:
    opacity 0.26s var(--ease),
    translate 0.34s var(--ease),
    scale 0.34s var(--ease),
    visibility 0s linear 0.34s;
  pointer-events: none;
}
.text-peek.is-open {
  opacity: 1;
  visibility: visible;
  translate: 0 0;
  scale: 1;
  pointer-events: auto;
  transition:
    opacity 0.26s var(--ease),
    translate 0.34s var(--ease),
    scale 0.34s var(--ease),
    visibility 0s;
}

/* The type is copied off the paragraph it opened from (see js/text-peek.js),
   so the same sentence carries on in the same voice instead of restarting in
   the panel's own. Only the colour is lifted: the clamped copy sits at 40-50%
   on its card, which is right for a background note and too faint for the
   thing the reader has just chosen to read. */
.text-peek__body { color: var(--text); }
.text-peek__body em { color: var(--accent); }
.text-peek__body > * + * { margin-top: 0.85em; }

/* Undo the clamp on the copy inside the panel.

   !important, and this is the case the keyword exists for: the panel holds
   CLONES of the clamped paragraphs, classes and all, and some of those caps
   are written against the class alone — body.scene-mode-ready .about-lead, at
   three classes deep. No selector reachable from here outranks that without
   becoming a sentence, and a clone that arrived here still clamped would
   defeat the entire feature. Everything else about the clone's styling is
   left exactly as it was. */
.text-peek__body > * {
  display: block !important;
  max-height: none !important;
  overflow: visible !important;
  max-width: none !important;
  margin-bottom: 0 !important;
}

/* A hairline of the accent along the top edge, the same signature the section
   headers use, so the panel reads as part of this page and not as a browser
   affordance that happened to appear. */
.text-peek::before {
  content: '';
  position: absolute;
  left: 20px;
  right: 20px;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent, rgba(219, 107, 43, 0.75) 22%, rgba(219, 107, 43, 0.75) 78%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .text-peek { transition: opacity 0.15s linear, visibility 0s linear 0.15s; translate: none; scale: 1; }
  .text-peek.is-open { transition: opacity 0.15s linear, visibility 0s; }
}
