/**
 * viewer2026.css — the project viewer: the `Selector` and the `Projects VISOR`
 * boards over the page. Shared by the home (index.html) and the project pages
 * (/projects/<slug>/, written by tools/projects.js); moved out of corpus2026.css
 * on 7-sep-2026 so a page can open the viewer without loading the corpus.
 * `--k` is desk2026.css's design pixel, redeclared on the dialog with the same
 * formula: the pages have no `--k` of their own. Loaded after corpus2026.css.
 */

.fl-viewer {
  --k: calc(min(100vw, 1520px) / 1520);
}

@media (max-width: 799px) {
  .fl-viewer {
    --k: calc(var(--fl-vw, 100vw) / 375);
  }
}

/* desk2026.css's two type bases, which the corpus relies on and the pages
   set differently (projects2026.css: `.fl-text` at 1.6, no nowrap). `:where`
   keeps the single-class specificity, so every viewer rule below still wins. */
:where(.fl-viewer) .fl-display {
  font-family: 'Gloock', Georgia, serif;
  font-weight: 400;
  letter-spacing: var(--fl-track);
  line-height: 1.2;
  white-space: nowrap;
}

:where(.fl-viewer) .fl-text {
  font-family: 'Lato', Arial, sans-serif;
  font-weight: 400;
  line-height: 1.2;
  white-space: nowrap;
}

/* corpus2026.css's helper, for the dialog's hidden heading on a page. */
.fl-viewer .fl-a11y {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ── project viewer ────────────────────────────────────────────────
   Two Penpot screens outside the corpus: the `Selector` (board `Selector -
   APThotel_still vs 360`, 1047137d…) and the ficha from `Projects VISOR`
   (2f4f762c…), both 1520x920. THE CANVAS HERE IS NOT THE PINNED 1520x920:
   the boards represent the whole window, so what is preserved is the
   RELATIONS — each block says which axis it anchors against and by which
   factor it scales. */

.fl-viewer {
  /* `<dialog>` brings a border, padding, `fit-content` width and auto margin. */
  position: fixed;
  inset: 0;
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  /* `contain` so the wheel does not chain to the page beneath. Not enough on
     its own — see `viewer.js`, which also restores the scroll on close — but
     it is the cheap half of the problem. */
  overflow: hidden;
  overscroll-behavior: contain;
  background: #fff;
  color: #000;
}

.fl-viewer::backdrop {
  background: #fff;
}

/* Opening and closing CROSS-FADE instead of cutting — declared invention,
   the board draws no transition. The close is orchestrated by `viewer.js`
   (`is-closing` and then `close()`); under `prefers-reduced-motion` the
   class is not even added. */
.fl-viewer[open] {
  animation: fl-viewer-in 0.25s ease;
}

.fl-viewer.is-closing {
  animation: fl-viewer-out 0.2s ease forwards;
}

@keyframes fl-viewer-in {
  from { opacity: 0; }
}

@keyframes fl-viewer-out {
  to { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .fl-viewer[open] {
    animation: none;
  }
}

.fl-selector,
.fl-sheet {
  position: absolute;
  inset: 0;
}

.fl-selector[hidden],
.fl-sheet[hidden] {
  display: none;
}

/* ── Selector — board `Selector - APThotel_still vs 360` (1047137d…) ──
   Two 559x677 CARDS on white — still at 94,121 and 360 at 845,121 (94 of
   left margin, 116 of right) — with the Gloock 48 label centred over each
   and a 20% black veil as the pointed state. The frame is the whole window;
   the design pixel is min(W/1520, H/920) because the pair of cards must
   fit. Positions hang off the centre with the board's offsets. */

.fl-selector {
  --u: min(calc(100vw / 1520), calc(100svh / 920));
}

.fl-sel-half {
  position: absolute;
  top: calc(50% - 339 * var(--u));
  width: calc(559 * var(--u));
  height: calc(677 * var(--u));
  margin: 0;
  padding: 0;
  border: 0;
  overflow: hidden;
  background: none;
  color: inherit;
  text-decoration: none;
  cursor: pointer;
}

.fl-sel-still { left: calc(50% - 666 * var(--u)); }
.fl-sel-tour { left: calc(50% + 85 * var(--u)); }

/* The assets come cropped from the old design at 761x920 (proportion .827);
   the new card measures 559x677 (.826) — the same to within 0.1%, so `cover`
   barely decides anything. If the pixel diff said otherwise, they get
   re-baked. */
.fl-sel-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* The 20% veil on hover is declared INVENTION: the board draws no hover
   state (its black@0.2 sits UNDER the image, invisible in the export); a
   soft veil is the closest thing to the tiles' language. */
.fl-sel-half::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.2);
  opacity: 0;
  transition: opacity 0.25s ease;
}

.fl-sel-half:hover::after,
.fl-sel-half:focus-visible::after {
  opacity: 1;
}

/* Gloock 48 / 1.92 / #FFFEFA, centred over its card: on the board the tour's
   label nails its card's centre (1125 vs 1124.5) and still's is off by 8.5 —
   it reads as centred and the rule wins. */
.fl-sel-label {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-size: calc(48 * var(--k));
  letter-spacing: calc(1.92 * var(--k));
  color: #fffefa;
  white-space: nowrap;
  pointer-events: none;
}

/* ── project ficha — board `Projects VISOR` (Penpot 2f4f762c…) ───────
   Frame `Projects - NordicHommeoffice` 1520x920, representing the whole
   window. The image fits inside 955x614 keeping proportion, centred on both
   axes — 283 = (1520-955)/2 and 153 = (920-613)/2. `--vw` and `--vh` are
   that box, set by `viewer.js`. Only the caption hangs off the photo: FLUSH
   with its left edge and +28 below the bottom one (794 - 766). The rest
   hangs off the WINDOW: `seguir viendo` centred at the bottom, the arrows
   40 from each edge and the `X` top right. */

/* THE WINDOW IS THE FRAME: the 1520x920 board represents the whole
   browser. `--u` is the DESIGN PIXEL and only THE PHOTO is drawn with it;
   labels, caption and glyphs go with `--k`. HEIGHT RULES (100svh/920),
   yielding only when the widest box (955) cannot fit leaving 80 per side
   for the arrows' lane — that 80 is declared invention. `--uv` is the pure
   VERTICAL ANCHOR (32 the X, 479 the arrows, 80 the `seguir viendo` from
   the bottom); the horizontal edge margins (40) stay with `--k`. At
   1520x920 the three factors are 1. */
.fl-viewer {
  --uv: calc(100svh / 920);
}

.fl-sheet {
  --u: min(calc(100svh / 920), calc((100vw - 160px) / 955));
}

/* The container receives focus on open — see `viewer.js` — and a container
   draws no ring: what is announced is the screen, not a control. */
.fl-sheet:focus {
  outline: none;
}

.fl-sheet-fig {
  position: absolute;
  inset: 0;
  margin: 0;
}

/* The views' canvas. `overflow: hidden` because during the slide two images
   coexist, the one leaving at the top and the one entering from below. */
.fl-sheet-views {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.fl-sheet-img {
  position: absolute;
  left: calc(50% - var(--vw) * var(--u) / 2);
  top: calc(50% - var(--vh) * var(--u) / 2);
  width: calc(var(--vw) * var(--u));
  height: calc(var(--vh) * var(--u));
  object-fit: cover;
  /* `transform` only: a project change touches `--vw`/`--vh`/`src` and must
     not animate; a view step moves `transform` and does. */
  transition: transform 0.6s ease;
}

/* A single text node in the file (#2077:119): `NordicHomeOffice fluint
   studio`, with Gloock 24 as base and a run in Lato Light 15 from `fluint`
   on. The 0.96 tracking is paragraph-level and thus falls on both runs —
   0.04em on the name and 0.064em on the caption — so it goes here in canvas
   units and not as `em`. It is split into two explicit lines: in the file
   the 227 box does it, and leaving it to the width would mean a long name
   breaking where it should not. */
.fl-sheet-caption {
  position: absolute;
  left: calc(50% - var(--vw) * var(--u) / 2);
  top: calc(50% + var(--vh) * var(--u) / 2 + 28 * var(--k));
  width: calc(227 * var(--k));
}

/* The caption hangs off the box, and views have different boxes: on a
   VIEW change it travels in step with the slide. Only then — `is-viewed` is
   set by `changeView` and removed by `paintSheet`: on a PROJECT change the
   photo enters dry and the caption with it. Invention — the board draws a
   single screen per project. */
.fl-sheet.is-viewed .fl-sheet-caption {
  transition: left 0.6s ease, top 0.6s ease;
}

.fl-sheet-name {
  display: block;
  font-size: calc(24 * var(--k));
  letter-spacing: calc(0.96 * var(--k));
}

/* Each run carries its own 0.04em tracking on the board — 0.96 for the name
   in Gloock 24 and 0.6 for the caption in Lato 15. */
.fl-sheet-studio {
  display: block;
  font-weight: 300;
  font-size: calc(15 * var(--k));
  letter-spacing: calc(0.6 * var(--k));
}

/* `seguir viendo` — board group: Lato Light Italic 16 text with 0.64 of
   tracking at 709,820 (92 wide) and `Arrow 1`, a vertical arrow of 10 with
   stroke 1 whose tip falls at x 810. The group (709..810) sits centred on
   the canvas — its centre is 759.5 on a canvas whose centre is 760 — so in x
   it hangs off the centre: 760 - 709 = 51 to the left. In y it hangs off the
   window's BOTTOM EDGE, not the centre: the board is the whole window and
   the text ends at 840, i.e. 80 from the edge (920 - 840). */
.fl-sheet-continue {
  position: absolute;
  left: calc(50% - 51 * var(--k));
  bottom: calc(80 * var(--uv));
  padding: 0;
  border: 0;
  background: none;
  font-size: calc(16 * var(--k));
  font-weight: 300;
  font-style: italic;
  letter-spacing: calc(0.64 * var(--k));
  color: #000;
  text-align: left;
  cursor: pointer;
}

/* Pressed in a chain, like the old `next project`: the area grows without
   moving anything drawn. Added, not on the board. */
.fl-sheet-continue::before {
  content: '';
  position: absolute;
  inset: calc(-14 * var(--k)) calc(-16 * var(--k));
}

/* `Arrow 1`. The glyph is `arrow-down-10.svg` (8x11), which already is this
   arrow: a line of 10 with a tip, stroke 1. Its vertical axis sits at the
   board's x 810, i.e. 101 from the text's start: 101 - 4 centres the svg's
   8. The stroke's `y` is 826..836, +6 from the text's top edge. */
.fl-sheet-continue::after {
  content: '';
  position: absolute;
  left: calc(97 * var(--k));
  top: calc(6 * var(--k));
  width: calc(8 * var(--k));
  height: calc(11 * var(--k));
  background: url('/assets/images/2026/arrow-down-10.svg') center / contain no-repeat;
}

/* The project arrows — `Arrow 2` (forward, right) and `Arrow 3` (back,
   left): a line of 16 with stroke 1.5, round tail and tip, painted 40 from
   their window edge and with the stroke at y 479. The same number the
   notebook reader's arrows already mount, which copied this board: the
   height is kept as a PROPORTION of the window (479/920), because the board
   is the whole window. The glyph is `arrow-viewer.svg`, built from the
   board's numbers (Penpot's SVG export comes back empty) and the head with
   `arrow-down-10.svg`'s proportions, which is the same language. */
.fl-sheet-arrow {
  position: absolute;
  top: calc(479 * var(--uv) - 5.5 * var(--k));
  width: calc(16 * var(--k));
  height: calc(11 * var(--k));
  padding: 0;
  border: 0;
  background: url('/assets/images/2026/arrow-viewer.svg') center / contain no-repeat;
  cursor: pointer;
}

.fl-sheet-next {
  right: calc(40 * var(--k));
}

.fl-sheet-prev {
  left: calc(40 * var(--k));
  transform: scaleX(-1);
}

/* THE SIDE COLUMN IS ARROW: the pressable area grows from the glyph to the
   white on its side — from the window edge to the photo's in width, and in
   height everything but a 100 strip at the top (the X) and at the bottom
   (the caption and `seguir viendo`). The column is the glyph's ::before,
   which keeps its 40/479; on `atras` the button's scaleX(-1) mirrors it. */
.fl-sheet-arrow::before {
  content: '';
  position: absolute;
  right: calc(-40 * var(--k));
  width: calc(50vw - var(--vw) * var(--u) / 2);
  top: calc(5.5 * var(--k) - 379 * var(--uv));
  height: calc(100svh - 200 * var(--uv));
}

.fl-sheet-arrow:focus-visible,
.fl-sheet-x:focus-visible,
.fl-sel-x:focus-visible,
.fl-sheet-continue:focus-visible {
  opacity: 0.6;
}

/* The `X` — the close this board DOES draw: the `X` character in Lato Light
   16, 10x20 box at 1470,32, i.e. 40 from the right edge (1520 - 1480). */
.fl-sheet-x,
.fl-sel-x {
  position: absolute;
  right: calc(40 * var(--k));
  top: calc(32 * var(--uv));
  padding: 0;
  border: 0;
  background: none;
  font-family: 'Lato', Arial, sans-serif;
  font-size: calc(16 * var(--k));
  font-weight: 300;
  line-height: 1.2;
  letter-spacing: 0;
  color: #000;
  cursor: pointer;
}

.fl-sheet-x::before,
.fl-sel-x::before {
  content: '';
  position: absolute;
  inset: calc(-16 * var(--k));
}

/* INVENTION, and marked: the file draws no close. It is hidden just like
   `.fl-a11y` while nobody looks for it, and appears the moment it receives
   keyboard focus — the only case where Esc is not enough, because it must be
   announceable. */
.fl-viewer-close {
  position: absolute;
  left: calc(40 * var(--k));
  top: calc(40 * var(--k));
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  border: 0;
  background: none;
  font-family: 'Lato', Arial, sans-serif;
  font-size: calc(16 * var(--k));
  white-space: nowrap;
  cursor: pointer;
}

.fl-viewer-close:focus-visible {
  width: auto;
  height: auto;
  padding: calc(8 * var(--k)) calc(16 * var(--k));
  overflow: visible;
  clip-path: none;
  background: #000;
  color: #fff;
}

@media (max-width: 799px) {
  /* ── the viewer on mobile (MBL_visor) ────────────────────────────
     The board draws the 335x254 card with its caption centred — Gloock 20
     over Lato 13 Light. */
  /* The viewer lives outside `.fl-corpus`; its `--k` is declared on the
     dialog at the top of this file. Here it only collapses its own factors. */
  .fl-viewer {
    --uv: var(--k);
  }

  .fl-sheet,
  .fl-selector {
    --u: var(--k);
  }

  .fl-selector {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: calc(24 * var(--k));
  }

  .fl-sel-half {
    position: relative;
    top: auto;
    left: auto;
    width: calc(220 * var(--k));
    height: calc(266 * var(--k));
  }

  .fl-sel-label {
    font-size: calc(32 * var(--k));
  }

  .fl-sel-x {
    position: fixed;
    top: calc(16 * var(--k));
    right: calc(16 * var(--k));
  }

  /* The ficha is the board's COLUMN: all the project's views stacked in
     335x254 cards (81/395/708 → pitch 313.5, gap 59.5) traversed by scroll;
     the project's caption stays FIXED at the screen's foot (board: 730..770
     of 812) with the project arrows flanking it. The views are stacked by
     viewer.js (.fl-extra-view); the canvas's slide does not run here. */
  .fl-sheet {
    display: block;
    padding: calc(81 * var(--k)) calc(20 * var(--k)) calc(96 * var(--k));
    overflow-y: auto;
    /* The column slides sideways between projects (below): a transform
       past the edge must not open a horizontal scroll. */
    overflow-x: hidden;
  }

  .fl-sheet-fig {
    position: static;
    width: auto;
  }

  .fl-sheet-views {
    position: static;
    width: 100%;
    aspect-ratio: auto;
    display: flex;
    flex-direction: column;
    gap: calc(59 * var(--k));
    /* The project change slides the whole column, the canvas's 0.6s
       (viewer.js `changeProject`). */
    transition: transform 0.6s ease;
  }

  /* The OUTGOING column of a project change (viewer.js `changeProject`): a
     throwaway clone pinned where the real one was seen, clipped to the
     screen so it adds no scroll, and out of the finger's way. */
  .fl-sheet-views.is-ghost {
    position: absolute;
    left: calc(20 * var(--k));
    right: calc(20 * var(--k));
    width: auto;
    overflow: hidden;
    pointer-events: none;
  }

  /* Each view at ITS proportion and WHOLE — the vertical one tall, the
     landscape one complete. The canvas box (--vw/--vh) is each photo's real
     proportion; the board draws uniform 254 cards. */
  .fl-sheet-img {
    position: static;
    width: 100%;
    height: auto;
    aspect-ratio: var(--vw) / var(--vh);
    object-fit: cover;
    transform: none !important;
    transition: none !important;
  }

  /* BLACK ink, not the board's white: the fixed caption crosses gaps and
     light backgrounds where the white vanished. */
  .fl-sheet-caption {
    position: fixed;
    /* 56 per side: the project arrows' gap (brickvisual). */
    left: calc(56 * var(--k));
    right: calc(56 * var(--k));
    /* Explicit `top: auto`: the canvas hangs the caption from a top that
       here beat the bottom and threw it below the screen (measured at
       768). */
    top: auto;
    bottom: calc(42 * var(--k));
    width: auto;
    margin: 0;
    text-align: center;
    color: #000;
    pointer-events: none;
    z-index: 2;
  }

  .fl-sheet-caption .fl-display {
    position: static;
    display: block;
    font-size: calc(20 * var(--k));
    color: #000;
  }

  .fl-sheet-caption .fl-text {
    position: static;
    display: block;
    font-size: calc(13 * var(--k));
    font-weight: 300;
    color: #000;
  }

  .fl-sheet-continue {
    display: none;
  }

  /* The arrows navigate PROJECTS, flanking the fixed caption: ← name → on
     the bottom edge, and scroll for the project's photos. Black, on a white
     viewer, with the canvas glyph as mask. */
  /* The glyph goes as background, NOT as mask: masking the button also
     clips its ::before's hit-test in Blink and the enlarged touch zone
     received no taps. The canvas's SVG is already black. */
  .fl-sheet-arrow {
    position: fixed;
    top: auto;
    bottom: calc(60 * var(--k));
    width: calc(18 * var(--k));
    height: calc(13 * var(--k));
    background: url('/assets/images/2026/arrow-viewer.svg') center / contain no-repeat;
    z-index: 3;
  }

  .fl-sheet-next {
    right: calc(20 * var(--k));
  }

  .fl-sheet-prev {
    left: calc(20 * var(--k));
  }

  /* The finger margin around the glyph, ~66x73px of zone per arrow. The
     caption in between steals no taps: `pointer-events: none`. */
  .fl-sheet-arrow::before {
    right: calc(-24 * var(--k));
    left: calc(-24 * var(--k));
    top: calc(-30 * var(--k));
    bottom: calc(-30 * var(--k));
    width: auto;
    height: auto;
  }


  .fl-sheet-x {
    position: fixed;
    top: calc(16 * var(--k));
    right: calc(16 * var(--k));
  }
}

@media (prefers-reduced-motion: reduce) {
  .fl-sheet-img,
  .fl-sheet-caption {
    transition: none !important;
  }
}
