/* ═══════════════════════════════════════════════════════════════════
   SOLVA SKIN — PRESENTATION LAYER
   Append to styles/solva.css. Additive only: this file changes no
   existing rule and defines no token.

   EVERY rule is scoped to `body.solva-skin`. A page opts in by adding that
   class; nothing else on the site can be reached. This is deliberate —
   the V1/V2 bleed happened because two builds shared a place, and the
   cheapest insurance against repeating it is that the new layer is
   unreachable from any page that has not asked for it. Reverting a page
   is removing one class.

   The tokens are NOT redefined here. They were verified hex-for-hex
   against the :root block already in solva.css.

   WHAT THIS LAYER ADDS
     · the datum + rail grid every screen hangs from
     · two rule weights (--datum, --hair) that invert on the green ground
     · the screen shell (scroll-snap) and the flow shell (viewport-locked)
     · form grammar: option lines, baseline-rule fields and selects
     · the arrival reveal, downward-only
   ═══════════════════════════════════════════════════════════════════ */

body.solva-skin{
  /* Layer-local only. Colour, type and spacing come from solva.css. */
  --datum:1px solid var(--ink);
  --hair:1px solid var(--cream-line);
  --rail:210px;
  --header-h:64px;       /* solva.css has no header token; every skin screen
                            offsets against this one. */
}

/* Viewport lock — OPT-IN, per page. The flow pages (free preview, region
   select, brief, delivery) fill the viewport and never scroll; the
   homepage must scroll. Add `solva-skin-flow` to <html> on a flow page only.
   Scoped so it can never reach a page that has not asked for it — an
   unconditional html{overflow:hidden} in a shared stylesheet is exactly
   how the homepage lost its scrollbar during prototyping. */
html.solva-skin-flow,
html.solva-skin-flow body{height:100%;overflow:hidden}

/* :where() keeps the reset scoped to opted-in pages but at ZERO specificity
   — a reset's job is to kill UA defaults, not to beat page rules. At the
   original (0,2,0) it silently zeroed every single-class margin/padding in
   solva-brief.html's own stylesheet (e.g. .step-nav's --sp-6 gap). */
:where(body.solva-skin) *, :where(body.solva-skin) *::before, :where(body.solva-skin) *::after{box-sizing:border-box;margin:0;padding:0}
html.solva-skin{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body.solva-skin{
  font-family:var(--sans);font-size:15px;line-height:1.55;
  color:var(--ink);background:var(--cream);-webkit-font-smoothing:antialiased;
}
body.solva-skin img{display:block;max-width:100%}
body.solva-skin a{color:inherit}
body.solva-skin :focus-visible{outline:3px solid var(--green);outline-offset:2px}
/* ── SITE HEADER — verbatim from the foundation ────────────────────
   Paper ground with a hairline. No blur, no shadow stacks; content
   slides under it. The homepage adds .overlay — transparent with cream
   type over the photographic hero, gaining the paper ground once
   scrolled past it. */
body.solva-skin .site-header{
  position:fixed;top:0;left:0;right:0;z-index:var(--z-sticky);
  height:var(--header-h);
  display:flex;align-items:center;justify-content:space-between;gap:var(--s3);
  padding:0 var(--s4);
  background:var(--paper);
  border-bottom:var(--hair);
  transition:background .25s var(--ease),border-color .25s var(--ease);
}
body.solva-skin .sh-wm{
  font-family:var(--serif);font-weight:700;font-size:22px;letter-spacing:-.015em;
  line-height:1;color:var(--ink);text-decoration:none;user-select:none;
  transition:color .25s var(--ease);
}
body.solva-skin .sh-wm span{color:var(--green);transition:color .25s var(--ease)}
body.solva-skin .sh-right{display:flex;align-items:center;gap:var(--s3)}
body.solva-skin .sh-link{
  font-size:12.5px;letter-spacing:.02em;color:var(--graphite);text-decoration:none;
  transition:color .18s var(--ease);
}
body.solva-skin .sh-link:hover{color:var(--green)}
body.solva-skin .lang-toggle{display:flex;border:var(--hair);transition:border-color .25s var(--ease)}
body.solva-skin .lang-btn{
  background:transparent;border:none;padding:6px 12px;
  font-size:12px;font-family:var(--sans);letter-spacing:.06em;cursor:pointer;
  color:var(--graphite);text-decoration:none;line-height:1.4;
  transition:background .15s var(--ease),color .15s var(--ease);
}
body.solva-skin .lang-btn.active{background:var(--green);color:var(--on-green)}
/* Transparent-over-hero state */
body.solva-skin .site-header.overlay{background:transparent;border-bottom-color:transparent}
body.solva-skin .site-header.overlay .sh-wm{color:var(--cream)}
body.solva-skin .site-header.overlay .sh-wm span{color:var(--cream)}
body.solva-skin .site-header.overlay .sh-link{color:rgba(244,241,234,.8)}
body.solva-skin .site-header.overlay .sh-link:hover{color:var(--cream)}
body.solva-skin .site-header.overlay .lang-toggle{border-color:rgba(244,241,234,.4)}
body.solva-skin .site-header.overlay .lang-btn{color:rgba(244,241,234,.8)}
body.solva-skin .site-header.overlay .lang-btn.active{background:var(--cream);color:var(--ink)}
/* ═══ FLOW ══════════════════════════════════════════════════════════
   Three steps, one screen each, no scrolling. Same composition as the
   homepage: a datum rule, the label on the rail, the heading and the
   content hanging from one edge. Nothing is boxed except the buttons.
   ================================================================== */

body.solva-skin .flow{height:100dvh;position:relative}
/* Flow panel. Renamed from .pane: the homepage uses .pane for its three
   process columns, and this unscoped display:none was hiding them. */
body.solva-skin .pane{
  position:absolute;inset:0;
  display:none;flex-direction:column;
  padding:calc(var(--header-h) + var(--s5)) 0 calc(56px + var(--s4));
}
body.solva-skin .pane.on{display:flex}
body.solva-skin .frame{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter)}
body.solva-skin .label{
  font-size:11px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-soft);
}
body.solva-skin .display{
  font-family:var(--serif);font-weight:700;
  font-size:clamp(40px,7vw,92px);line-height:.98;letter-spacing:-.03em;
}
body.solva-skin .lead{font-size:17px;line-height:1.5;color:var(--graphite);max-width:56ch}
body.solva-skin .head, body.solva-skin .body{
  display:grid;grid-template-columns:var(--rail) 1fr;gap:var(--s4);
  align-items:start;
}
body.solva-skin .head{border-top:var(--datum);padding-top:var(--s2);margin-bottom:var(--s4)}
body.solva-skin .head > .label{padding-top:6px;line-height:1.35}
body.solva-skin .head .display{margin-bottom:var(--s3)}
body.solva-skin .body > :first-child{grid-column:2}
body.solva-skin .body{flex:1;min-height:0}
body.solva-skin .body > :first-child{min-height:0;overflow-y:auto}
/* ── The bar. One hairline and a line of type, exactly like the hero's
      direction bar — the step on the left, the actions on the right. */
body.solva-skin .bar{
  position:absolute;left:0;right:0;bottom:0;z-index:6;
  display:flex;align-items:center;justify-content:space-between;
  height:56px;padding:0 var(--s4);
  border-top:var(--hair);
}
body.solva-skin .bar .label{color:var(--ink-soft)}
body.solva-skin .bar-acts{display:flex;align-items:center;gap:var(--s3)}
body.solva-skin .back{
  background:none;border:none;padding:0;cursor:pointer;
  font-family:var(--sans);font-size:14px;color:var(--ink-soft);
  transition:color .16s var(--ease);
}
body.solva-skin .back:hover{color:var(--ink)}
body.solva-skin .btn{
  display:inline-flex;align-items:center;gap:10px;
  min-height:44px;padding:0 var(--s3);
  font-family:var(--sans);font-size:14px;font-weight:600;
  text-decoration:none;border:1px solid transparent;cursor:pointer;
  transition:background .16s var(--ease),color .16s var(--ease),border-color .16s var(--ease);
}
body.solva-skin .btn-solid{background:var(--green);color:var(--on-green);border-color:var(--green)}
body.solva-skin .btn-solid:hover{background:var(--green-deep);border-color:var(--green-deep)}
body.solva-skin .btn-solid em{font-style:normal;font-weight:400;color:var(--on-green-dim)}
body.solva-skin .btn-line{background:none;border-color:var(--ink);color:var(--ink)}
body.solva-skin .btn-line:hover{background:var(--ink);color:var(--cream)}
body.solva-skin .btn-ghost{background:none;color:var(--cream);border-color:rgba(244,241,234,.5)}
body.solva-skin .btn-ghost:hover{background:var(--cream);color:var(--ink);border-color:var(--cream)}
body.solva-skin .btn:disabled{opacity:.4;cursor:not-allowed}
/* ── FORM GRAMMAR — options are lines, fields are baseline rules ──── */
body.solva-skin .opts{display:grid;gap:0;max-width:640px}
body.solva-skin .opt{
  display:flex;align-items:baseline;gap:var(--s2);
  padding:var(--s2) 0;border-bottom:var(--hair);cursor:pointer;
  transition:color .16s var(--ease);
}
body.solva-skin .opt:first-child{border-top:var(--hair)}
body.solva-skin .opt input{position:absolute;opacity:0;pointer-events:none}
body.solva-skin .opt .mark{
  font-family:var(--serif);font-size:15px;color:var(--cream-line);
  min-width:2ch;transition:color .16s var(--ease);
}
body.solva-skin .opt .txt{font-size:17px}
body.solva-skin .opt .sub{display:block;font-size:14px;color:var(--graphite);margin-top:2px}
body.solva-skin .opt:hover .mark{color:var(--graphite)}
body.solva-skin .opt:has(input:checked) .mark{color:var(--green)}
body.solva-skin .opt:has(input:checked) .txt{font-weight:600}
body.solva-skin .opt:has(input:focus-visible){outline:3px solid var(--green);outline-offset:3px}
body.solva-skin .where{margin-top:var(--s4);max-width:520px}
body.solva-skin .where label{display:block;font-size:13px;font-weight:600;margin-bottom:6px}
body.solva-skin .field{
  width:100%;font-family:var(--sans);font-size:16px;
  padding:12px 0;border:none;border-bottom:var(--datum);
  background:none;color:var(--ink);
}
body.solva-skin .field::placeholder{color:var(--cream-line)}
body.solva-skin .field:focus{outline:none;border-bottom-color:var(--green)}
body.solva-skin select.field{
  appearance:none;-webkit-appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%234A4A46' stroke-width='1.4' fill='none' stroke-linecap='square'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 2px center;padding-right:26px;
}
body.solva-skin select.field:invalid{color:var(--graphite)}
body.solva-skin .req{color:var(--green);font-weight:600}
body.solva-skin .grid2{display:grid;grid-template-columns:1fr 1fr;gap:var(--s3);max-width:640px}
body.solva-skin .grid2 .where{margin-top:0}

@media (max-width:880px){body.solva-skin .grid2{grid-template-columns:1fr}}
/* ═══ HOME ═══ */
/* ── SCREENS ───────────────────────────────────────────────────────
   Scroll-snap, proximity not mandatory — nothing traps the reader, and
   the second and third screenfuls are where engagement is highest, so
   they get full height rather than being compressed. */
/* Mandatory, and each screen stops the scroll rather than being skipped
   past — so a flick lands a screen in place instead of leaving you to
   nudge it straight. */
html.solva-skin{scroll-snap-type:y mandatory}
body.solva-skin .screen{
  min-height:100svh;scroll-snap-align:start;
  display:flex;flex-direction:column;justify-content:center;
  padding:calc(var(--header-h) + var(--s5)) 0 var(--s5);
  position:relative;
}
body.solva-skin .frame{width:100%;max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter)}
/* ── TYPE SCALE — contrast, not uniform mediums ────────────────────
   Big display against small labels, with as little as possible in the
   middle. Everything sat at "medium" before, which is why it read flat. */
body.solva-skin .label{
  font-size:11px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink-soft);
}
body.solva-skin .display{
  font-family:var(--serif);font-weight:700;
  font-size:clamp(40px,7vw,92px);line-height:.98;letter-spacing:-.03em;
}
body.solva-skin .lead{font-size:17px;line-height:1.5;color:var(--graphite);max-width:56ch}
/* The datum governs the whole screen: the label sits in the left column,
   and BOTH the heading and the body below it hang from the same second
   column. Before, the heading was indented and the content was not, so
   nothing on the page shared a left edge. */
body.solva-skin .head, body.solva-skin .body{
  display:grid;grid-template-columns:var(--rail) 1fr;gap:var(--s4);
  align-items:start;
}
body.solva-skin .head{
  border-top:var(--datum);
  padding-top:var(--s2);margin-bottom:var(--s4);
}
body.solva-skin .head > .label{padding-top:6px;line-height:1.35}
body.solva-skin .head .display{margin-bottom:var(--s3)}
/* The left cell of .body is empty — it holds the alignment, nothing else. */
body.solva-skin .body > :first-child{grid-column:2}
/* ── FORAGING CUE ──────────────────────────────────────────────────
   People scroll only when they have a reason to. Each screen ends by
   naming what the next one answers — quiet, but it is the reason. */
body.solva-skin .next{
  position:absolute;left:0;right:0;bottom:var(--s4);
  pointer-events:none;
}
body.solva-skin .next-in{
  max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter);
  display:grid;grid-template-columns:var(--rail) 1fr;gap:var(--s4);
}
body.solva-skin .next-in a{grid-column:2;justify-self:start}
body.solva-skin .next a{
  pointer-events:auto;font-size:12px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-soft);text-decoration:none;font-weight:600;
  border-bottom:var(--hair);padding-bottom:3px;
  transition:color .18s var(--ease),border-color .18s var(--ease);
}
body.solva-skin .next a:hover{color:var(--green);border-color:var(--green)}
/* ── 01 · THE LOT ──────────────────────────────────────────────────── */
body.solva-skin .hero{padding:0;justify-content:stretch;min-height:100svh}
body.solva-skin .stage{
  position:relative;flex:1;min-height:0;overflow:hidden;
  background:var(--ink);-webkit-user-select:none;user-select:none;touch-action:pan-y;
}
body.solva-skin .layer{position:absolute;inset:0}
body.solva-skin .layer img{width:100%;height:100%;object-fit:cover}
/* Concept underneath, unclipped. The lot photo is on top and is clipped
   back from the right, so dragging left uncovers the building. */
body.solva-skin .concept{z-index:1}
body.solva-skin .lot{z-index:2;clip-path:inset(0 calc(100% - var(--split,50%)) 0 0)}
body.solva-skin .stage::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(102deg,rgba(14,26,20,.9) 0%,rgba(14,26,20,.7) 34%,rgba(14,26,20,.24) 60%,transparent 78%);
}
body.solva-skin .hero-copy{
  position:absolute;left:0;bottom:0;z-index:5;
  max-width:min(680px,62vw);max-height:calc(100% - var(--header-h));
  padding:var(--s4) var(--s4) calc(56px + var(--s4));color:var(--cream);
}
body.solva-skin .hero-copy .label{color:rgba(244,241,234,.7);margin-bottom:var(--s3)}
body.solva-skin .hero-copy h1{
  font-family:var(--serif);font-weight:700;
  font-size:clamp(40px,7vw,92px);line-height:.98;letter-spacing:-.03em;
  margin-bottom:var(--s3);
}
body.solva-skin .hero-copy p{color:var(--on-green-dim);max-width:56ch;font-size:17px;line-height:1.5}
body.solva-skin .acts{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s4);align-items:center}
body.solva-skin .btn{
  display:inline-flex;align-items:center;gap:10px;
  min-height:48px;padding:0 var(--s3);
  font-family:var(--sans);font-size:14px;font-weight:600;
  text-decoration:none;border:1px solid transparent;cursor:pointer;
  transition:background .16s var(--ease),color .16s var(--ease),border-color .16s var(--ease);
}
body.solva-skin .btn-solid{background:var(--green);color:var(--on-green);border-color:var(--green)}
body.solva-skin .btn-solid:hover{background:var(--green-deep);border-color:var(--green-deep)}
body.solva-skin .btn-solid em{font-style:normal;font-weight:400;color:var(--on-green-dim)}
body.solva-skin .btn-ghost{background:none;color:var(--cream);border-color:rgba(244,241,234,.5)}
body.solva-skin .btn-ghost:hover{background:var(--cream);color:var(--ink);border-color:var(--cream)}
body.solva-skin .btn-line{background:none;border-color:var(--ink);color:var(--ink)}
body.solva-skin .btn-line:hover{background:var(--ink);color:var(--cream)}
body.solva-skin .acts-note{width:100%;margin-top:var(--s1);font-size:13px;color:rgba(244,241,234,.68)}
/* Style chips — the three lead languages, one camera, one lot. */
/* One line across the base of the image, built like the footer: label at
   the far left, the three directions running to the far right edge, a
   hairline above. Not a floating panel. */
/* One hairline and a line of type. No ground, no cells, no fills — the
   same grammar the cream screens use, where a rule and space do the work
   that a box would otherwise do. */
body.solva-skin .dirbar{
  position:absolute;left:0;right:0;bottom:0;z-index:5;
  display:flex;align-items:center;justify-content:space-between;
  height:56px;padding:0 var(--s4);
  border-top:1px solid rgba(244,241,234,.3);
}
body.solva-skin .dirbar .label{
  color:rgba(244,241,234,.6);font-size:11px;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;white-space:nowrap;
}
body.solva-skin .dir-row{display:flex;align-items:center;gap:var(--s4)}
body.solva-skin .chip{
  background:none;border:none;padding:0;cursor:pointer;
  font-family:var(--sans);font-size:14px;white-space:nowrap;
  color:rgba(244,241,234,.6);
  transition:color .16s var(--ease);
}
body.solva-skin .chip:hover{color:var(--cream)}
/* Selected is stated by weight and colour, not by a filled cell. */
body.solva-skin .chip[aria-pressed="true"]{color:var(--cream);font-weight:600}
/* Type, not chips. The scrim already carries the contrast on the left;
   the right-hand label is gone — the direction bar names the concept. */
body.solva-skin .tag{
  position:absolute;top:calc(var(--header-h) + var(--s3));z-index:5;
  font-size:11px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(244,241,234,.72);
}
body.solva-skin .tag-l{left:var(--s4)}
body.solva-skin .grip{
  position:absolute;top:0;bottom:0;left:var(--split,50%);
  width:1px;background:rgba(244,241,234,.85);z-index:4;cursor:ew-resize;
}
body.solva-skin .grip::before{
  content:"";position:absolute;top:50%;left:50%;
  width:44px;height:44px;transform:translate(-50%,-50%);
  background:var(--cream);border-radius:50%;
}
body.solva-skin .grip::after{
  content:"‹ ›";position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);font-size:15px;color:var(--ink);letter-spacing:.08em;
  white-space:nowrap;
}
/* Keyboard access only. It must NOT take pointer events: at inset:0 it
   covered the whole stage and swallowed every click meant for the
   buttons and the direction bar. Dragging is handled on .stage itself;
   the input stays focusable and arrow-keys still work. */
body.solva-skin .reveal{
  position:absolute;inset:0;opacity:0;width:100%;height:100%;
  z-index:6;pointer-events:none;
}
body.solva-skin .reveal:focus-visible + .grip{outline:3px solid var(--cream);outline-offset:3px}
/* ── 02 · FREE PREVIEW ─────────────────────────────────────────────
   The free render lives on the homepage, as it does in production. */
body.solva-skin .free-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5);align-items:start}
/* Caption under the homepage free-preview CTA — plain text, never a link.
   (The homepage stopped using .drop: its tile navigated, it never accepted
   files. The .drop base below stays for the REAL dropzones on preview.html
   and solva-brief.html.) */
body.solva-skin .free-hint{margin-top:var(--s2);font-size:14px;color:var(--graphite);max-width:38ch}
body.solva-skin .drop{
  display:block;border:1px dashed var(--cream-line);background:var(--paper);
  padding:var(--s5) var(--s3);text-align:center;cursor:pointer;
  transition:border-color .18s var(--ease),background .18s var(--ease);
}
body.solva-skin .drop:hover, body.solva-skin .drop.over{border-color:var(--green);background:var(--green-tint)}
body.solva-skin .drop strong{display:block;font-family:var(--serif);font-size:24px;font-weight:600;margin-bottom:var(--s1)}
body.solva-skin .drop em{font-style:normal;font-size:14px;color:var(--graphite);display:block;max-width:38ch;margin:0 auto}
body.solva-skin .drop-shot{margin-top:var(--s2);aspect-ratio:16/9;background-size:cover;background-position:center;display:none;border:var(--hair)}
body.solva-skin .drop-shot.on{display:block}
body.solva-skin .free-list{list-style:none}
body.solva-skin .free-list li{
  font-size:15px;padding:12px 0;border-bottom:var(--hair);
  display:flex;gap:var(--s2);
}
body.solva-skin .free-list li::before{content:"—";color:var(--green)}
body.solva-skin .free-note{font-size:13px;color:var(--graphite);margin-top:var(--s3)}
/* ── 03 · PRICING ──────────────────────────────────────────────────── */
body.solva-skin .tbl{width:100%;border-collapse:collapse}
body.solva-skin .tbl th, body.solva-skin .tbl td{
  text-align:left;padding:var(--s2) var(--s3) var(--s2) 0;
  border-bottom:var(--hair);font-size:15px;vertical-align:top;
}
body.solva-skin .tbl thead th{border-bottom:var(--datum);padding-bottom:var(--s2)}
body.solva-skin .tbl tfoot td{border-bottom:none;padding-top:var(--s3)}
body.solva-skin .tier{font-family:var(--serif);font-size:26px;font-weight:600;display:block;letter-spacing:-.015em}
body.solva-skin .price{display:block;font-size:13px;color:var(--graphite);margin-top:6px}
/* Reserved in every header cell, shown in one — otherwise the flagged
   column starts lower and no tier name shares a baseline with another. */
body.solva-skin .flag{
  display:block;font-size:11px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--green);margin-bottom:6px;line-height:1.4;
}
body.solva-skin .flag-slot{visibility:hidden}
body.solva-skin .feat{color:var(--graphite)}
body.solva-skin .yes{color:var(--green);font-weight:600}
body.solva-skin .no{color:var(--cream-line)}
body.solva-skin .note{font-size:13px;color:var(--graphite);margin-top:var(--s3);max-width:74ch}
/* ── 04 · PROCESS ──────────────────────────────────────────────────── */
body.solva-skin .steps{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s5)}
body.solva-skin .step{border-top:var(--datum);padding-top:var(--s3)}
body.solva-skin .step .n{font-family:var(--serif);font-size:15px;color:var(--graphite);margin-bottom:var(--s2)}
body.solva-skin .step h3{
  font-family:var(--serif);font-weight:600;font-size:26px;
  letter-spacing:-.015em;line-height:1.14;margin-bottom:var(--s2);
  /* Two lines reserved: one heading wraps and the others do not, and the
     paragraphs below have to start on the same line regardless. */
  min-height:calc(2 * 1.14em);
}
body.solva-skin .step p{color:var(--graphite)}
/* ── 05 · LIMITATIONS ──────────────────────────────────────────────── */
body.solva-skin .limits{
  background:var(--green);color:var(--on-green);
  --datum:1px solid rgba(244,241,234,.55);
  --hair:1px solid rgba(244,241,234,.22);
}
body.solva-skin .limits .label{color:rgba(244,241,234,.6)}
body.solva-skin .limits .display{max-width:18ch}
body.solva-skin .limits .lead{color:var(--on-green-dim)}
body.solva-skin .two{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5)}
body.solva-skin .limits ul{list-style:none}
body.solva-skin .limits li{font-size:15px;color:var(--on-green-dim);padding:12px 0;border-bottom:var(--hair)}
body.solva-skin .limits li:first-child{border-top:var(--hair)}
body.solva-skin .limits p{color:var(--on-green-dim);margin-top:var(--s3);max-width:56ch}
/* The footer is short, so it snaps to the bottom of the viewport rather
   than becoming a mostly-empty sixth screen. */
/* The footer is the bottom band of the final screen, not a snap stop of
   its own — reaching it should not cost a whole extra screen of scrolling. */
body.solva-skin .limits{display:flex;flex-direction:column;justify-content:center;padding-bottom:0}
body.solva-skin .limits > .frame{flex:1;display:flex;flex-direction:column;justify-content:center;min-height:0}
/* Scoped to .limits, the homepage footer's route-context ancestor —
   start.html now has its own .ftr, and bare these cream-ground rules
   would bleed into it (scoping convention, #315/#316). */
body.solva-skin .limits .ftr{
  flex:none;margin-top:var(--s4);
  border-top:var(--hair);
  padding:var(--s3) 0;font-size:13px;color:rgba(244,241,234,.7);
}
body.solva-skin .limits .ftr a{color:rgba(244,241,234,.85)}
body.solva-skin .limits .ftr .sh-wm{color:var(--cream)}
body.solva-skin .limits .ftr .sh-wm span{color:var(--cream)}
body.solva-skin .limits .ftr-in{display:flex;justify-content:space-between;gap:var(--s3);flex-wrap:wrap}
body.solva-skin .limits .ftr a{text-decoration:none}
/* Tap targets — pad, don't grow (the convention the brief already uses). */
@media (pointer:coarse){
  body.solva-skin .sh-link,body.solva-skin .next a{position:relative}
  body.solva-skin .sh-link::after,body.solva-skin .next a::after{
    content:"";position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
    width:max(100%,44px);height:max(100%,44px);
  }
}

@media (max-width:880px){body.solva-skin .head{grid-template-columns:1fr;gap:var(--s2);margin-bottom:var(--s4)}
body.solva-skin .free-grid, body.solva-skin .steps, body.solva-skin .two{grid-template-columns:1fr;gap:var(--s4)}
body.solva-skin .site-header{padding:0 var(--gutter)}
body.solva-skin .hero-copy{max-width:none;padding:var(--s3) var(--s3) calc(52px + var(--s3))}
body.solva-skin .stage::after{background:linear-gradient(180deg,rgba(14,26,20,.5) 0%,rgba(14,26,20,.35) 35%,rgba(14,26,20,.92) 100%)}
body.solva-skin .dirbar{padding:0 var(--s3);height:52px}
body.solva-skin .dirbar .label{display:none}
body.solva-skin .dir-row{flex:1;justify-content:space-between;gap:var(--s2)}
body.solva-skin .chip{font-size:13px}
body.solva-skin .tag{display:none}
body.solva-skin .sh-right .sh-link{display:none}
body.solva-skin .tbl th:nth-child(2), body.solva-skin .tbl td:nth-child(2), body.solva-skin .tbl th:nth-child(4), body.solva-skin .tbl td:nth-child(4){display:none}
body.solva-skin .screen{padding:calc(var(--header-h) + var(--s4)) 0 var(--s5)}
body.solva-skin .next{bottom:var(--s3)}}

@media (max-height:700px){body.solva-skin .hero-copy p{display:none}
/* A screen taller than the viewport must never become unreachable —
     mandatory snap can fight the scroll on short windows. */
html.solva-skin{scroll-snap-type:y proximity}}
/* ═══ REVEAL ════════════════════════════════════════════════════════
   Time-based transitions, fired when a screen arrives.

   NOT animation-timeline:view(). A scroll-driven animation is driven by
   scroll POSITION, and mandatory snap teleports the position — the whole
   entry range is traversed during the jump, so the animation is finished
   before the screen lands and is never seen. On a snapping page it has
   to be time-based.

   The hidden state requires html.js-motion, which JS adds only when it
   has an observer to remove it with. And `.seen` is never taken off once
   set, so nothing can be re-hidden by a scroll-back race.
   ================================================================== */
html.solva-skin.js-motion .screen [data-rv]{
  transition:opacity 1.15s var(--ease),transform 1.15s var(--ease);
  transition-delay:calc(var(--rv-i,0) * 130ms);
}
html.solva-skin.js-motion .screen:not(.seen) [data-rv]{
  opacity:0;transform:translateY(24px);
}
/* Re-arming happens only when a screen is fully above the viewport, and
   with the transition suppressed — so the reset is never seen as a
   fade-out, only as the next pass playing again. */
html.solva-skin.js-motion .screen.rearm [data-rv], html.solva-skin.js-motion .screen.rearm [data-wipe]{transition:none!important}
html.solva-skin.js-motion .screen [data-wipe]{
  /* End state reaches past the box — with line-height under 1 the
     descenders on g, p and y sit outside it and would be cropped. */
  clip-path:inset(0 -12% -35% -4%);
  transition:clip-path 1.35s cubic-bezier(.16,1,.3,1);
  transition-delay:calc(var(--rv-i,0) * 130ms);
}
html.solva-skin.js-motion .screen:not(.seen) [data-wipe]{
  clip-path:inset(0 -12% 100% -4%);
}
/* The hero is the first thing seen, so it plays on load. */
@keyframes solva-rise{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:none}}

@keyframes solva-wipe{from{clip-path:inset(0 -12% 100% -4%)}to{clip-path:inset(0 -12% -35% -4%)}}

@media (prefers-reduced-motion: no-preference){html.solva-skin .hero-copy .label{animation:solva-rise 1.1s var(--ease) both .2s}
html.solva-skin .hero-copy h1{animation:solva-wipe 1.4s cubic-bezier(.16,1,.3,1) both .38s}
html.solva-skin .hero-copy p{animation:solva-rise 1.1s var(--ease) both .78s}
html.solva-skin .hero-copy .acts{animation:solva-rise 1.1s var(--ease) both 1s}
html.solva-skin .tag-l{animation:solva-rise 1.1s var(--ease) both 1.18s}
html.solva-skin .dirbar{animation:solva-rise 1.1s var(--ease) both 1.3s}}


@media (prefers-reduced-motion:reduce){html.solva-skin.js-motion .screen [data-rv], html.solva-skin.js-motion .screen:not(.seen) [data-rv]{opacity:1;transform:none;transition:none}
html.solva-skin.js-motion .screen [data-wipe], html.solva-skin.js-motion .screen:not(.seen) [data-wipe]{clip-path:none;transition:none}
html.solva-skin .hero-copy > *, html.solva-skin .tag-l, html.solva-skin .dirbar{animation:none}}

@media print{html.solva-skin.js-motion .screen [data-rv], html.solva-skin.js-motion .screen:not(.seen) [data-rv], html.solva-skin.js-motion .screen [data-wipe], html.solva-skin.js-motion .screen:not(.seen) [data-wipe]{
    opacity:1!important;transform:none!important;clip-path:none!important;transition:none!important;
  }
html.solva-skin *{animation:none!important}}

@media (prefers-reduced-motion:reduce){html.solva-skin{scroll-behavior:auto;scroll-snap-type:none}
body.solva-skin *{transition:none!important}}
/* ═══ PREVIEW ═══ */
/* ── 01 · the photograph. The drop target is the content, so it gets the
      column and nothing else competes with it. */
/* Scoped to .preview — the page's route-context ancestor, taken at this
   page's conversion as promised in #316 (interim .flow scoping). The brief
   section's drop takes .brief the same way, so neither can reach the other. */
body.solva-skin .preview .drop{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;cursor:pointer;
  min-height:min(46vh,420px);
  border:1px dashed var(--cream-line);
  transition:border-color .18s var(--ease),background .18s var(--ease);
}
body.solva-skin .preview .drop:hover, body.solva-skin .preview .drop.over{border-color:var(--green);background:var(--green-tint)}
body.solva-skin .preview .drop strong{font-family:var(--serif);font-size:clamp(22px,2.6vw,30px);font-weight:600;margin-bottom:var(--s1)}
body.solva-skin .preview .drop em{font-style:normal;font-size:15px;color:var(--graphite);max-width:40ch}
body.solva-skin .preview .shot{
  min-height:min(46vh,420px);background-size:cover;background-position:center;
  display:none;position:relative;
}
body.solva-skin .preview .shot.on{display:block}
body.solva-skin .preview .shot .swap{
  position:absolute;right:var(--s2);bottom:var(--s2);
  background:none;border:1px solid rgba(244,241,234,.5);color:var(--cream);
  font-family:var(--sans);font-size:12px;padding:8px 14px;cursor:pointer;
}
body.solva-skin .preview .shot .swap:hover{background:var(--cream);color:var(--ink);border-color:var(--cream)}
/* Shared flow-page hint — ONE rule; the byte-identical brief-section
   duplicate was consolidated here (CLAUDE.md skin-CSS convention). */
body.solva-skin .hint{font-size:13px;color:var(--graphite);margin-top:var(--s2)}
/* ── 02 · the details — the real /free-preview intake. ─────────────
   Constrain the shell's scroll region exactly as start.html does: pin
   the body row, stretch the child, clip the container, so a tall form
   scrolls instead of spilling under the bar. */
body.solva-skin .preview .body{grid-template-rows:minmax(0,1fr);align-items:stretch;overflow:hidden}
/* Progressive reveal — the six later fields are absent until the region
   is chosen (.pv-open on the grid), then cascade in with a subtle
   staggered rise (--pv-i set inline per field) and STAY. The space
   appears in one paint (display flip on the shared class), so nothing
   reflows mid-animation; only opacity/transform animate. Reduced motion
   gets the flip with no entrance. */
body.solva-skin .preview .pv-later{display:none}
body.solva-skin .preview .grid2.pv-open .pv-later{display:block}
@media (prefers-reduced-motion: no-preference){
  body.solva-skin .preview .grid2.pv-open .pv-later{
    animation:pv-field-in .45s ease both;
    animation-delay:calc(var(--pv-i, 0) * 70ms);
  }
}
@keyframes pv-field-in{
  from{opacity:0;transform:translateY(8px)}
  to{opacity:1;transform:none}
}
/* Quiet inline note under a field (the region-switch style reset) —
   informational graphite, never the error red. */
body.solva-skin .preview .field-note{font-size:13px;color:var(--graphite);margin-top:var(--s1)}
/* De-emphasized "(optional)" marker inside a field label. */
body.solva-skin .preview .where .lbl-opt{color:var(--graphite);font-weight:400}
/* Warm limit invitation vs technical error — the 429 is NEVER the red box. */
body.solva-skin .preview .notice{
  max-width:640px;margin-top:var(--s3);padding:var(--s3);
  background:var(--green-tint);
}
body.solva-skin .preview .notice p{margin-bottom:var(--s2);max-width:56ch}
body.solva-skin .preview .notice-error{background:none;border:1px solid var(--cream-line)}
body.solva-skin .preview .notice-error b{color:var(--ink)}
/* ── 03 · the concept ──────────────────────────────────────────────
   The wait is not a spinner over nothing — it is their own lot, full
   screen. When the render lands it appears underneath and the lot is
   clipped back across it, so the reveal is the product's own mechanic
   rather than a loading state that ends. */
body.solva-skin .result{padding:0}
body.solva-skin .preview .plate{position:absolute;inset:0;background:var(--ink);overflow:hidden;-webkit-user-select:none;user-select:none;touch-action:pan-y}
body.solva-skin .preview .plate .layer{position:absolute;inset:0}
body.solva-skin .preview .plate img{width:100%;height:100%;object-fit:cover;position:absolute;inset:0}
body.solva-skin .preview .p-concept{z-index:1}
body.solva-skin .preview .p-lot{z-index:2;background-size:cover;background-position:center;clip-path:inset(0 calc(100% - var(--split,100%)) 0 0)}
body.solva-skin .preview .plate::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(102deg,rgba(14,26,20,.9) 0%,rgba(14,26,20,.7) 34%,rgba(14,26,20,.24) 60%,transparent 78%);
}
/* One small lockup over the image, bottom right. Not a diagonal tile —
   a repeating watermark reads as distrust; a single mark reads as a
   preview. The real constraint is that the file is never served: the
   concept only exists inside the comparison on this page. */
body.solva-skin .preview .mark-wm{
  position:absolute;right:var(--s4);bottom:calc(56px + var(--s4));z-index:5;
  display:flex;align-items:baseline;gap:8px;
  padding:9px 14px;border:1px solid rgba(244,241,234,.35);
  color:rgba(244,241,234,.85);
}
body.solva-skin .preview .mark-wm b{font-family:var(--serif);font-weight:700;font-size:16px;color:var(--cream)}
body.solva-skin .preview .mark-wm span{font-size:10px;font-weight:600;letter-spacing:.16em;text-transform:uppercase}
body.solva-skin .preview .p-tag{
  position:absolute;left:var(--s4);top:calc(var(--header-h) + var(--s3));z-index:5;
  font-size:11px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(244,241,234,.72);
}
body.solva-skin .preview .gap{
  display:block;margin-top:var(--s2);font-size:14px;
  color:rgba(244,241,234,.68);max-width:52ch;
}
body.solva-skin .preview .share-row{display:flex;gap:var(--s2);align-items:center;flex-wrap:wrap;margin-top:var(--s2)}
body.solva-skin .preview .share-row button{
  background:none;border:none;padding:0;cursor:pointer;font-family:var(--sans);
  font-size:13px;color:rgba(244,241,234,.75);
  border-bottom:1px solid rgba(244,241,234,.35);padding-bottom:2px;
}
body.solva-skin .preview .share-row button:hover{color:var(--cream);border-bottom-color:var(--cream)}
body.solva-skin .preview .result-copy{
  position:absolute;left:0;bottom:0;z-index:4;
  max-width:min(660px,62vw);max-height:calc(100% - var(--header-h));
  padding:var(--s4) var(--s4) calc(56px + var(--s4));color:var(--cream);
}
body.solva-skin .preview .result-copy .label{color:rgba(244,241,234,.7);margin-bottom:var(--s3)}
body.solva-skin .preview .result-copy h2{
  font-family:var(--serif);font-weight:700;
  font-size:clamp(34px,5.4vw,72px);line-height:.98;letter-spacing:-.03em;
  margin-bottom:var(--s3);
}
body.solva-skin .preview .result-copy p{color:var(--on-green-dim);font-size:17px;line-height:1.5;max-width:52ch}
body.solva-skin .preview .send{display:flex;gap:var(--s2);margin-top:var(--s4);flex-wrap:wrap;align-items:center}
body.solva-skin .preview .send .field{
  border-bottom-color:rgba(244,241,234,.5);color:var(--cream);
  max-width:300px;flex:1;min-width:200px;
}
body.solva-skin .preview .send .field::placeholder{color:rgba(244,241,234,.5)}
body.solva-skin .preview .send .field:focus{border-bottom-color:var(--cream)}
body.solva-skin .preview .sent{color:var(--cream);font-size:15px;display:none}
body.solva-skin .preview .sent.on{display:block}
/* The wait, stated as stages rather than a percentage — nothing here
   knows how long a studio read takes, and an invented number is found
   out the moment it stalls. */
body.solva-skin .preview .status{margin-top:var(--s3);color:rgba(244,241,234,.8);font-size:15px;position:relative;padding-left:22px}
/* Continuous working pulse — a ::before so it survives the stage-text
   innerHTML rewrites. Visible liveness between the ~8s stage swaps:
   "working" and "frozen" look different at any moment. Hidden with the
   whole status line by .status.done. */
body.solva-skin .preview .status::before{
  content:"";position:absolute;left:0;top:6px;width:9px;height:9px;border-radius:50%;
  background:var(--cream);
  animation:pv-pulse 1.6s var(--ease) infinite;
}
@keyframes pv-pulse{0%,100%{opacity:.25;transform:scale(.8)}50%{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  body.solva-skin .preview .status::before{animation:none;opacity:.8;transform:none}
}
body.solva-skin .preview .status b{display:block;font-weight:600;color:var(--cream);margin-bottom:4px}
body.solva-skin .preview .status.done{display:none}
body.solva-skin .preview .after-ready{display:none}
body.solva-skin .preview .after-ready.on{display:block}
/* Scoped to the preview result pane. The prototype kept these under
   [data-route="/preview"]; flattened to body.solva-skin they overrode the
   HOMEPAGE hero's .grip/.reveal (same class, later in the file) — the
   handle sat at opacity:0 waiting for an .on the homepage never adds, and
   the keyboard slider was display:none. .result is the route ancestor. */
body.solva-skin .result .grip{
  position:absolute;top:0;bottom:0;left:var(--split,100%);
  width:1px;background:rgba(244,241,234,.85);z-index:5;cursor:ew-resize;
  opacity:0;transition:opacity .5s var(--ease);
}
body.solva-skin .result .grip.on{opacity:1}
body.solva-skin .grip::before{
  content:"";position:absolute;top:50%;left:50%;
  width:44px;height:44px;transform:translate(-50%,-50%);
  background:var(--cream);border-radius:50%;
}
body.solva-skin .grip::after{
  content:"‹ ›";position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);font-size:15px;color:var(--ink);letter-spacing:.08em;
}
/* Keyboard access only — see the homepage note. Pointer events would
   block the email field and the buttons sitting under it. */
body.solva-skin .result .reveal{
  position:absolute;inset:0;opacity:0;width:100%;height:100%;
  z-index:6;pointer-events:none;display:none;
}
body.solva-skin .result .reveal.on{display:block}
body.solva-skin .reveal:focus-visible + .grip{outline:3px solid var(--cream);outline-offset:3px}
body.solva-skin .result .bar{border-top-color:rgba(244,241,234,.3)}
body.solva-skin .result .bar .label{color:rgba(244,241,234,.6)}
body.solva-skin .result .bar .back{color:rgba(244,241,234,.7)}
body.solva-skin .result .bar .back:hover{color:var(--cream)}
/* ── IMMERSIVE REVEAL — after the first divider drag or 5s, the page JS
   adds .immersed and the overlay chrome (scrim, copy, bar) fades ~300ms
   so the comparison reads at full brightness; the watermark stays and
   the centered pill keeps the CTA reachable. A tap that is not the
   handle or the pill toggles the chrome back. prefers-reduced-motion:
   the global no-transition rule below makes the same toggle instant —
   no separate reduced-motion path needed. */
body.solva-skin .preview .plate::after{transition:opacity .3s var(--ease)}
body.solva-skin .preview .result-copy{transition:opacity .3s var(--ease)}
body.solva-skin .result .bar{transition:opacity .3s var(--ease)}
body.solva-skin .result.immersed .plate::after{opacity:0}
body.solva-skin .result.immersed .result-copy{opacity:0;pointer-events:none}
body.solva-skin .result.immersed .bar{opacity:0;pointer-events:none}
body.solva-skin .preview .cta-pill{
  position:absolute;left:50%;bottom:var(--s3);transform:translateX(-50%);
  z-index:7;border-radius:999px;white-space:nowrap;
  opacity:0;pointer-events:none;
  transition:opacity .3s var(--ease);
}
body.solva-skin .result.immersed .cta-pill{opacity:1;pointer-events:auto}

@media (max-width:880px){body.solva-skin .head, body.solva-skin .body{grid-template-columns:1fr;gap:var(--s2)}
body.solva-skin .body > :first-child{grid-column:1}
body.solva-skin .site-header{padding:0 var(--gutter)}
body.solva-skin .sh-right .sh-link{display:none}
body.solva-skin .step{padding:calc(var(--header-h) + var(--s3)) 0 calc(52px + var(--s3))}
body.solva-skin .bar{height:52px;padding:0 var(--gutter)}
body.solva-skin .bar .label{display:none}
body.solva-skin .bar-acts{width:100%;justify-content:space-between}
body.solva-skin .preview .result-copy{max-width:none;padding:var(--s3) var(--s3) calc(52px + var(--s3))}
body.solva-skin .preview .plate::after{background:linear-gradient(180deg,rgba(14,26,20,.5) 0%,rgba(14,26,20,.35) 30%,rgba(14,26,20,.92) 100%)}}

@media (prefers-reduced-motion:reduce){body.solva-skin *{transition:none!important}}
/* ═══ START ═══ */
/* ── REGION — two rows, single tap. No sub-lists, no expanding. ──────
   Scoped to .start, the page's route-context ancestor on start.html
   (scoping convention, #315/#316) — was [data-route="/start"] in the
   prototype; bare it would be the next .drop-style collision. */
/* Constrain the shell's scroll region: the flow grammar puts
   overflow-y:auto on .body's first child, but with auto-sized grid rows
   and align-items:start the child grows past the row and SPILLS under
   the bar instead of scrolling. Pin the single row to the body height
   and stretch the child so the overflow actually scrolls. */
body.solva-skin .start .body{grid-template-rows:minmax(0,1fr);align-items:stretch;overflow:hidden}
body.solva-skin .start .rows{max-width:820px}
body.solva-skin .start .row{
  display:grid;grid-template-columns:1fr auto;gap:var(--s3);align-items:center;
  padding:var(--s4) 0;border-bottom:var(--hair);
  text-decoration:none;color:inherit;
  transition:padding-left .18s var(--ease);
}
body.solva-skin .start .row:first-of-type{border-top:var(--hair)}
body.solva-skin .start .row:hover{padding-left:var(--s2)}
body.solva-skin .start .row h2{font-family:var(--serif);font-weight:600;font-size:clamp(26px,3.4vw,40px);letter-spacing:-.02em}
body.solva-skin .start .row p{color:var(--graphite);font-size:15px;margin-top:6px;max-width:46ch}
body.solva-skin .start .row .arrow{font-size:22px;color:var(--green)}
/* The single coming-soon line — quiet, not a tap target. */
body.solva-skin .start .row-soon{
  display:flex;align-items:baseline;justify-content:space-between;gap:var(--s3);
  padding:var(--s3) 0;
}
body.solva-skin .start .row-soon > span:first-child{
  font-family:var(--serif);font-weight:600;font-size:20px;
  letter-spacing:-.01em;color:var(--graphite);opacity:.6;
}
body.solva-skin .start .soon-tag{
  font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--ink-soft);border:var(--hair);padding:3px 9px;
}
/* Legal footer under the bar (solva-brief.html's footer pattern). The
   locked viewport splits: the pane takes the remaining height (its bar
   stays absolute at ITS bottom), the footer sits beneath — so the
   footer never overlaps the bar and survives any wrap height. */
body.solva-skin .start{display:flex;flex-direction:column}
body.solva-skin .start .pane{position:relative;flex:1;min-height:0}
/* Shared with the brief's per-step footer (identical pair consolidated per
   the FLOW/HOME convention). NOTE the selectors differ in shape: .start is
   the start page's <main> class, .brief is the brief page's BODY class. */
body.solva-skin .start .ftr, body.solva-skin.brief .ftr{
  flex:none;width:100%;max-width:var(--maxw);margin:0 auto;
  padding:var(--s3) var(--gutter);border-top:var(--hair);
  font-size:12px;color:var(--graphite);
  display:flex;justify-content:space-between;flex-wrap:wrap;gap:var(--s1);
}
body.solva-skin .start .ftr .dot, body.solva-skin.brief .ftr .dot{color:var(--green)}
body.solva-skin .start .ftr a, body.solva-skin.brief .ftr a{color:var(--green);text-decoration:none}
/* Inside a brief step (applyStep moves the node into the active section's
   flex column) margin-top:auto pins it to the step's bottom edge — always
   at the end of the content, never fixed. The section already carries the
   gutter, so the footer sheds its own horizontal padding there. */
body.solva-skin.brief .sec .ftr{margin-top:auto;padding:var(--s3) 0 0}
/* ═══ BRIEF ═══ */
/* ── BRIEF — the paid intake. Four steps, one screen each. ─────────── */
/* The prototype-brief .two/.drop rules that sat here are DELETED, not
   scoped: solva-brief.html converted as a RE-SKIN of its existing markup
   (INTEGRATION.md §4 — every id and handler kept), so the prototype's
   brief drop/two shapes will never exist. The page opts in via
   <body class="solva-skin brief"> and firewalls the shared-grammar
   collisions in its own stylesheet. */
body.solva-skin .thumbs{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:var(--s2);margin-top:var(--s3)}
body.solva-skin .thumb{position:relative;aspect-ratio:4/3;background-size:cover;background-position:center;background-color:var(--cream-line)}
body.solva-skin .thumb button{
  position:absolute;top:0;right:0;width:30px;height:30px;cursor:pointer;
  background:rgba(26,26,26,.72);color:var(--cream);border:none;font-size:15px;line-height:1;
}
/* (.hint consolidated into the shared flow-page rule — see PREVIEW section) */
/* Review reads as rows, not a card. */
body.solva-skin .rev{max-width:760px}
body.solva-skin .rev-row{display:grid;grid-template-columns:200px 1fr;gap:var(--s3);padding:var(--s2) 0;border-bottom:var(--hair)}
body.solva-skin .rev-row:first-child{border-top:var(--hair)}
body.solva-skin .rev-k{font-size:11px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-soft);padding-top:3px}
body.solva-skin .rev-v{font-size:16px}
body.solva-skin .rev-total{font-family:var(--serif);font-size:28px;font-weight:600;letter-spacing:-.015em}
body.solva-skin .small{font-size:13px;color:var(--graphite);margin-top:var(--s3);max-width:70ch}

@media (max-width:880px){body.solva-skin .two{grid-template-columns:1fr}
body.solva-skin .rev-row{grid-template-columns:1fr;gap:4px}}
/* ═══ DELIVERY ═══ */
/* ── DELIVERY ──────────────────────────────────────────────────────
   Two states at one address, scoped to .delivery — the page's
   route-context ancestor (scoping convention, #315/#316/#319).
   The prototype's 4-step tracker (.track/.trow/.dot/.when) is DELETED,
   not scoped: it implied a step-by-step precision the pipeline does not
   report, so the pending state is a single honest message and the
   tracker's rules must not survive to invite it back. */
body.solva-skin .delivery .shots{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s2)}
body.solva-skin .delivery .img{position:relative;aspect-ratio:3/2;background:var(--ink);overflow:hidden}
body.solva-skin .delivery .img img{width:100%;height:100%;object-fit:cover}
body.solva-skin .delivery .img .brand{
  position:absolute;left:0;right:0;bottom:0;padding:7px 10px;
  background:rgba(26,26,26,.72);color:rgba(244,241,234,.85);
  font-size:10px;letter-spacing:.1em;text-transform:uppercase;
  display:flex;justify-content:space-between;gap:var(--s1);
}
body.solva-skin .delivery .sizes{display:flex;gap:var(--s3);margin-top:var(--s1)}
body.solva-skin .delivery .sizes button{background:none;border:none;padding:0;cursor:pointer;font-family:var(--sans);font-size:13px;color:var(--ink-soft);transition:color .16s var(--ease)}
body.solva-skin .delivery .sizes button:hover{color:var(--green)}
/* Was .flow-scoped at #316 (splitting it from the homepage's .acts);
   now the page exists, it takes the page ancestor as promised there. */
body.solva-skin .delivery .acts{display:flex;gap:var(--s3);align-items:center;flex-wrap:wrap;margin-top:var(--s4)}
body.solva-skin .delivery .link{
  background:none;border:none;font-family:var(--sans);
  font-size:14px;color:var(--ink-soft);border-bottom:var(--hair);
  padding:0 0 2px;text-decoration:none;cursor:pointer;
}
body.solva-skin .delivery .link:hover{color:var(--green)}
/* Hydration-pending controls: present for the future endpoint, honest now. */
body.solva-skin .delivery .link:disabled,
body.solva-skin .delivery .sizes button:disabled{opacity:.4;cursor:not-allowed}
body.solva-skin .delivery .link:disabled:hover{color:var(--ink-soft)}
body.solva-skin .delivery .order{display:flex;gap:var(--s4);flex-wrap:wrap;font-size:13px;color:var(--ink-soft)}
body.solva-skin .delivery .order b{color:var(--ink);font-weight:600}

@media (max-width:880px){body.solva-skin .delivery .shots{grid-template-columns:1fr}}