/* ob-shell.css — the one shell Ocean Basket wears everywhere.
   ---------------------------------------------------------------------------
   Before this file the product read as two apps: the doc-097 landing pages
   (cool navy #14224e, grey-white page, 4-item nav) and ocean-basket-app.html
   (deep navy #0a1140, warm cream, 5-item white nav). Crossing between them
   changed the palette AND the shape of the bottom bar, which is the single
   loudest "this is a different app" signal a phone user gets.

   The landing look wins — it is the 31-07-2026 mockup the owner approved.

   ⚠ The app cannot <link> this file: it is the installable PWA and has to keep
   working from cache with no network. So the three blocks marked
   OB-TOKENS / OB-HOME / OB-NAV below are duplicated verbatim inside
   ocean-basket-app.html's <style>. `node tools/verify-shell-sync.mjs` fails if
   they ever drift — do not hand-edit one copy without the other. Everything
   outside those sentinels is landing-only and the app does not need it. */

/* ==== BEGIN OB-TOKENS ==== */
:root{
  --ink:#14224e; --ink2:#1b2f7d; --body:#2c3a66; --mut:#6b7688;
  --page:#f5f8fb; --card:#ffffff; --line:#dfe7f2; --tint:#e9f1fa; --tint2:#edf3fb; --cream:#faf3e3;
  --gilt:#1ba8d3; --gilt-d:#147a9c;
  --ok:#2f7d46; --okbg:#e5f5ea; --okln:#b9e0c6;
  --warn:#c07b16; --warnbg:#fdf1de; --warnln:#f0d9ad;
  --bad:#c2402f; --badbg:#fde8e6; --badln:#f2c3ba;
  --navbar:#ffffff;
  /* doc 105 "Recommended A" — every value below was sampled off the design pack
     render at 300dpi, not picked by eye. The cyan trio (--sky) is used for
     exactly three things in the pack: the divider rule, headline line 2, and the
     CTA pill. It is deliberately NOT --gilt: --gilt stays the interactive accent
     on transactional buttons, and the accent guard polices it separately. */
  --hero1:#062560; --hero2:#072e71; --field:#06245f; --plate-nv:#001a5d;
  --sky:#22c1eb; --sky-cta:#16bbe5; --badge:#e5f5f8;
  --card-t:#092e67; --card-s:#6a7b8e; --ring:#c9d8e2;
  --navline:#dce6ed; --navon:#087f9b; --navoff:#8291a2;
  /* Measured off pack pages 12-27 at 300dpi by two independent passes that
     agreed. These are NOT interchangeable with the families above: the pack's
     success green (#12845c) is a teal-green, not --ok's olive; its amber is
     more saturated than --warn; and its primary CTA is a lighter navy than
     --card-t. Using the near-neighbours is what makes a rebuild look "nearly
     right" and read as a different app. */
  --cta:#084a91; --totalbar:#082f68; --ribbon:#0d88a6;
  --info-bg:#e6f5f8; --info-ac:#0ba0bd; --info-tx:#21546a;
  --good:#12845c; --good-bg:#dff5e9;
  --amber-bg:#fff1c9; --amber-tx:#986600;
  --num:#0a376d; --strong:#09244f; --value:#183454; --ph:#8a98a8;
  --sans:'Outfit',-apple-system,BlinkMacSystemFont,sans-serif; --script:'Yellowtail',cursive;
  --serif:'Noto Serif',Georgia,'Times New Roman',serif; --ui:'Cabin','Outfit',sans-serif;
  /* the front-page handoff sets everything in Inter — see OB-HOME */
  --sans-hero:'Inter',-apple-system,BlinkMacSystemFont,'Cabin',sans-serif;
  /* 82px read as a slab under every screen; an iOS tab bar is ~49-56pt. 64px is
     slim without shrinking the tap target — the cells keep min-height:48px. This
     one value also re-seats .screen, .cartbar, .toast and the install banner,
     which all offset from it. (owner 11-08: "clean and professional (slim)") */
  --max:480px; --r:14px; --btn-r:10px; --nav-h:64px;
}
/* ==== END OB-TOKENS ==== */

*{box-sizing:border-box}
/* overscroll-behavior:none kills iOS Safari's elastic drag. Owner, 2026-08-11:
   "somehow I can scroll to the black parts of the app which must not happen. I see
   this on other pages as well." It is not scrolling — the home document measures
   scrollHeight === innerHeight with nothing below the fold — it is the rubber-band,
   which drags the whole document past its end and shows whatever is behind <body>.
   ocean-basket-app.html already set this on its own body; these four landing pages
   (index / local / travel / stock) are the ones that never did, which is exactly the
   "other pages" in the report. */
html,body{margin:0;padding:0;overscroll-behavior:none}
/* THE FIELD BEHIND THE COLUMN, 30-08 (c). Was #0a0a0a — a near-black that existed only
   to letterbox a 480px column on a desktop, and read as the app being switched off
   around the edges. Owner supplied the replacement: a near-white paper with faint
   contour-wave line work, the same family as the sea paths drawn inside the hero.

   `cover`, not `repeat`, and that is the whole reason this is one 941x1672 file rather
   than a tile. The artwork is not seamless — it is a single drawn field, so butting
   copies of it together puts a visible ridge down every join, and the joins would land
   in the gutters, which is the only place anyone ever sees this. Scaled to cover, the
   left and right gutters are simply the left and right of one continuous picture. It is
   soft enough that upscaling costs nothing: at 1440 wide the image runs at 1.53x and the
   lines are still clean.

   `fixed` pins the positioning area to the viewport, so the backdrop holds still while
   the scrolling landing documents move over it. Home and the app never scroll (both are
   overflow:hidden), so there it changes nothing.

   #e8eced is the artwork's own ground colour, sampled off it — so a browser that cannot
   decode WebP, or a first paint before the 62 KB arrives, shows the same tone rather
   than a flash of something else. That solid IS the fallback: a CSS background gets no
   <picture>, and image-set() with type() needs a newer browser than plain WebP does. */
body{background:#e8eced url(./img/bg-waves.webp) center/cover no-repeat fixed;
  font-family:var(--sans);color:var(--body);-webkit-font-smoothing:antialiased}
/* …and belt-and-braces for the bounce itself: #0a0a0a exists only to letterbox the
   480px .site on a desktop. At phone widths .site fills the screen, so that colour is
   unreachable EXCEPT by dragging past the end — which is the black he saw. Match the
   page there instead, so a bounce shows nothing at all. body.home overrides to #fff
   below on its own. */
/* 30-08 (c): this override is KEPT even though the black it was written against is gone.
   At phone widths .site fills the screen, so the field above is unreachable except by
   dragging past the end — and a bounce should show the page, not the backdrop. It is the
   shorthand, so it clears the image too; that is deliberate. */
@media (max-width:480px){body{background:var(--page)}}
.site{max-width:var(--max);margin:0 auto;min-height:100vh;background:var(--page);
  box-shadow:0 0 40px rgba(0,0,0,.5);position:relative;
  padding-bottom:calc(var(--nav-h) + env(safe-area-inset-bottom) + 8px)}
/* body.home's background is set inside OB-HOME (doc 105 made it navy) */

/* The navy back-bar the sub pages used to draw is gone (owner 07-08): every
   landing document now shares the white .site-head below. The app's inner
   screens keep their own .topbar — that markup lives in the app file. */

/* ---------- buttons ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:0;cursor:pointer;
  text-decoration:none;font-family:var(--sans);font-weight:600;font-size:15px;border-radius:var(--btn-r);
  padding:13px 22px;background:var(--ink);color:#fff;line-height:1}
.btn.ghost{background:#fff;color:var(--ink)}
.btn.big{display:flex;width:auto;margin:12px 14px 0;padding:14px 18px}
.btn svg{width:20px;height:20px}

/* ---------- badges ---------- */
.badge{font-size:13px;font-weight:600;border-radius:9px;padding:6px 12px;white-space:nowrap}
.badge.ok{background:var(--okbg);color:var(--ok);border:1px solid var(--okln)}
.badge.warn{background:var(--warnbg);color:var(--warn);border:1px solid var(--warnln)}
.badge.bad{background:var(--badbg);color:var(--bad);border:1px solid var(--badln)}

/* ==== BEGIN OB-HOME ==== */
/* Home surface — built from OCB_App_Front_Page_Vector_Developer_Handoff.pdf,
   page 2. Every value below was READ OUT OF THAT FILE, not measured off a
   picture: positions and sizes from the page's content stream, type sizes and
   colours from its text operators, artwork from its own embedded images.

   ARTBOARD 369 x 801 pt. --u is one artboard point, so the screen scales as a
   single piece and every number here is the handoff's own figure.

   Font is INTER (ExtraBold / Bold / SemiBold) per pdffonts — not Cabin, which is
   what the rest of the app uses and what an earlier pass wrongly assumed here.

   The drawer stays even though this page has no burger: it is the only route to
   Profile, and the app opens it from its own header. */
/* ---------- drawer (doc 109 T4) ----------
   A drawer that actually slides: the element stays in the DOM so the scrim can
   fade and the panel can translate; visibility gates tap-through and delays its
   own hide until the exit animation is done. Reduced-motion gets the old
   instant open. Row anatomy: icon + label; the row for the page you are ON
   carries .on (inset bar + tint); WhatsApp is marked as leaving the site. */
.drawer{position:fixed;inset:0;z-index:90;visibility:hidden;transition:visibility 0s .26s}
.drawer.open{visibility:visible;transition:visibility 0s}
.drawer .scrim{position:absolute;inset:0;background:rgba(16,25,66,.45);opacity:0;transition:opacity .26s ease}
.drawer.open .scrim{opacity:1}
.drawer .panel{position:absolute;top:0;left:0;bottom:0;width:272px;background:#fff;
  padding:0 0 max(22px, env(safe-area-inset-bottom)) 0;overflow-y:auto;
  box-shadow:4px 0 30px rgba(0,0,0,.25);
  transform:translateX(-105%);transition:transform .26s cubic-bezier(.2,.7,.2,1)}
.drawer.open .panel{transform:none}
@media (prefers-reduced-motion:reduce){
  .drawer,.drawer .scrim,.drawer .panel{transition:none}
}
.drawer .phead{display:flex;align-items:center;justify-content:space-between;
  padding:calc(14px + env(safe-area-inset-top)) 10px 12px 22px;border-bottom:1px solid var(--line);margin-bottom:6px}
.drawer .pbrand{font-family:var(--ui);font-size:15px;font-weight:700;color:var(--ink)}
.drawer .pclose{background:none;border:0;padding:10px;cursor:pointer;color:var(--ink);display:flex}
.drawer .pclose svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round}
.drawer .glab{padding:14px 22px 5px;font-family:var(--ui);font-size:10.5px;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;color:var(--mut)}
.drawer .panel a{display:flex;align-items:center;gap:12px;padding:12px 22px;color:var(--ink);
  text-decoration:none;font-weight:600;font-size:15px}
.drawer .panel a svg{flex:0 0 auto;width:18px;height:18px;stroke:currentColor;fill:none;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;opacity:.75}
.drawer .panel a.on{background:var(--tint);box-shadow:inset 3px 0 0 var(--ink2);font-weight:700}
.drawer .panel a.on svg{opacity:1}
/* hover only where hover exists — a phone's sticky :hover reads as a second
   active row — and never on the .on row, whose tint must not be overridden */
@media (hover:hover){ .drawer .panel a:not(.on):hover{background:var(--tint2)} }
.drawer .panel a:active{background:var(--tint)}
.drawer .panel a:focus-visible{outline:2px solid var(--ink2);outline-offset:-2px}
.drawer .panel a .ext{margin-left:auto;width:14px;height:14px;opacity:.55}
.drawer .panel .dv{height:1px;background:var(--line);margin:8px 0}

/* ---------- shared header (every surface EXCEPT home) ---------- */
/* Drawn 16 times inside the PWA and once per landing sub-page, which is why it
   lives in a synced block. Home has none — the handoff has no header. */
.site-head{position:sticky;top:0;z-index:50;background:var(--hero1);border-bottom:1px solid rgba(255,255,255,.08);
  display:flex;align-items:center;justify-content:center;padding:8px 14px;min-height:54px}
.site-head .burger{background:none;border:0;padding:6px;cursor:pointer;color:#fff;display:flex;
  position:absolute;left:8px;top:50%;transform:translateY(-50%)}
.site-head svg{width:27px;height:27px}
.site-head .logo{display:flex;align-items:center;text-decoration:none;cursor:pointer;
  width:150px;height:34px;background:url(./img/brand/wordmark-white.png) center/contain no-repeat}
.site-head .logo .mark,.site-head .logo .word{display:none}
.site-head .hpill{position:absolute;right:12px;top:50%;transform:translateY(-50%);
  font-family:var(--ui);font-size:11px;font-weight:700;line-height:1;
  padding:6px 11px;border-radius:999px;background:rgba(255,255,255,.16);color:#fff;text-decoration:none}
.site-head .hpill.warn{background:var(--warn);color:#fff}
.site-head .hpill.ok{background:var(--ok);color:#fff}

/* ---------- checkout step ribbon ---------- */
.stepbar{background:#0d88a6;color:#fff;font-family:var(--ui);font-weight:400;
  font-size:10px;letter-spacing:.01em;height:30px;display:flex;align-items:center;
  justify-content:center;text-align:center}

/* ==================== HOME (handoff page 2) ==================== */
body.home{background:#fff}
/* --u is one artboard point, and it is clamped on BOTH axes.

   It used to be derived from width alone. That silently assumed the screen was at
   least as tall as 801 artboard points, i.e. an aspect ratio of 1:2.17 — a 19.5:9
   phone. It holds on the reference device (390x844 needs 847 and gets 844, 3px
   short, invisible) and nowhere else:

       iPhone SE 2/3  375x667   design needs 814   short by 147
       common Android 360x640   design needs 781   short by 141
       any landscape  844x390   design needs 1042  short by 652

   Because the hero is `flex:1 1 auto` while its children are absolutely positioned
   at fixed --u multiples — the headline, wordmark and CTA anchored to the TOP, the
   plate and wave anchored to the BOTTOM — a hero shorter than 556.5 --u drives the
   two sets through each other. The plate rode up over the headline and the CTA
   landed on the food; in landscape the whole hero was gone. Nothing scrolled out of
   it, because this container is overflow:hidden, so the collision was the final
   state rather than a transient.

   Taking the min against height scales the artboard as ONE piece to fit whatever
   screen it is on, which is what this block always claimed to do. It is a uniform
   scale, so every proportion the pixel-diff work established survives exactly; the
   cost is 0.3% on the reference device (u 1.057 -> 1.054).

   The safe-area inset has to come out of the height first: box-sizing is border-box
   globally, so padding-bottom eats the content box, and an artboard sized against
   the full 100dvh would push the bottom card under the home indicator.

   The site stays FULL WIDTH. Only the artboard's *content* is scaled and centred
   (see `.hero .art` and `.cards` below) — the navy, the sea, the plate and the wave
   all still run edge to edge. Scaling the whole site instead put bars down both
   sides, which is not what the render shows. */
/* FOLLOW-UP, doc 003. The two-axis clamp above stopped the collision, but it paid
   for the whole height deficit in SCALE — and a uniform shrink spends the abundant
   resource (width) to solve a shortage in the scarce one (height). Measured, as the
   share of the screen width the design turns into side padding:

       390x844 reference          7.6%   <- the handoff's own intent
       390x694 WhatsApp browser  24.0%
       392x656 owner's phone     28.5%   <- nearly 4x the intent

   The artboard is 1:2.17 and that last viewport is 1:1.67. Note that full width is
   arithmetically OUT OF REACH: closing a 30% aspect gap needs 184 points of height
   and the entire design contains 141.75 points of air (52.5 top pad + 27.25 under
   the wordmark + 62 above the CTA). Zeroing every gap still does not fit. Something
   other than air has to give, or the page has to scroll — and scrolling was measured
   and rejected: at full width, 292px of a 656px screen falls below the fold, taking
   the wide card and two thirds of both navy cards with it.

   So the deficit is paid out of the air AND the plate band, which is a bottom-
   anchored photograph and can lose height by cropping where a gap cannot. --sq is
   that deficit in px; each element below subtracts its own share of it.

   Two properties this shape buys, both load-bearing:

   - --sq is BOUNDED by the 700 floor at (801-700)*u, so every gap has a guaranteed
     minimum at ANY viewport, however extreme. No media query, no conditional, and
     no way back to the collision this block was written to fix.
   - At 1:2.17 or taller --sq is 0 and every value below reduces to the handoff's own
     number, so the pixel-diff work is untouched where it was judged. The reference
     device measures 100% of width-bound now — marginally BETTER than the 0.3% this
     comment charged above, because the width branch wins outright.

   Owner's phone: padding 28.5% -> 18.2%, design 14.4% larger. WhatsApp: 24% -> 13.1%. */
/* HOME IS A FIXED SCREEN AND MUST NOT SCROLL AT ALL — second pass, 2026-08-11.
   overscroll-behavior alone was not enough: the owner's screenshot shows a real
   SCROLLBAR, so the document genuinely exceeds the viewport on his phone. Neither
   engine here reproduces it (scrollHeight === clientHeight on the deployed page in
   both), so this is iOS viewport behaviour, not a stray element — which is exactly
   why it is fixed structurally rather than by hunting further:

   - dvh -> svh. `dvh` is the CURRENT viewport and changes as Safari's toolbars
     retract; at the moment of layout it can resolve to the large value while the
     visible area is still the small one, and the difference is scrollable. `svh` is
     the SMALLEST viewport — toolbars shown — so the screen can never be laid out
     taller than what is actually visible. Order matters below: dvh first as the
     fallback for engines without svh, svh second so it wins where supported.
   - overflow:hidden on html AND body, not just .site. .site was already clipping its
     own children; nothing was stopping the DOCUMENT from scrolling around it.
   The :has() is what keeps this scoped to home — the other four landing documents
   scroll normally and must keep doing so. */
html:has(body.home),body.home{height:100dvh;height:100svh;overflow:hidden}
/* The field the artboard sits in once the window is wider than the column — see the
   gutter note on body.home .site. WAS #051261, the hero gradient's own 38% stop, chosen
   so the navy gutters read as one continuous field with the hero rather than as bars.
   Owner, 30-08: the blue and the black both go, replaced by the paper texture on `body`
   above. Home has to restate it rather than inherit, because body.home overrides the
   background here for its own reasons — and it must be the SAME declaration, or the
   home gutters and every other document's gutters drift apart.

   This does change what home reads as, deliberately: the navy column now sits ON a light
   field instead of dissolving into a dark one, so the artboard reads as a card. That is
   the ask, not a side effect. */
body.home{background:#e8eced url(./img/bg-waves.webp) center/cover no-repeat fixed}
/* justify-content, 2026-08-30: .hero is capped (see its max-height), so on an over-tall
   window the column has slack. Left to default flex-start it fell BELOW the cards and the
   page just stopped, which reads as broken. space-between puts it between the wave and the
   cards instead — the wave already dissolves the hero into white there, so the slack reads
   as a generous white field with the cards seated on the bottom edge. */
body.home .site{display:flex;flex-direction:column;min-height:0;overflow:hidden;
  justify-content:space-between;
  height:100dvh;height:100svh;
  background:#fff;padding-bottom:env(safe-area-inset-bottom);
  --h:calc(100dvh - env(safe-area-inset-bottom));
  --h:calc(100svh - env(safe-area-inset-bottom));
  /* ---------- THE ARTBOARD IS SIZED BY BOTH DIMENSIONS, 2026-08-30 ----------
     Owner, on a wide window against his phone: "the only thing that is different is
     wider screen but components are similar". That is the whole spec, and --max being a
     flat 480px is what broke it: --u already takes the SMALLER of the width and height
     scales, but the COLUMN did not, so on a short window everything shrank except the
     plate band — which is aspect-locked to the column width — and the band swelled to
     72% of the hero (38% on a phone), crushing the type and shrinking the fisherman.

     Every earlier attempt today treated that as a plate problem (cap it, crop it, fade
     it) and every one of them damaged the artwork. It was never the plate. It was the
     column. Tie the column to the same scale as everything else — 369 artboard points
     of --u — and the whole composition scales as one piece, at every size, with nothing
     cropped and nothing crushed.

     Measured, against the phone as the reference:
                        column  crop  plate/hero  fisherman/hero  headline/column
       392x760 phone      392    0%     38.4%         45.4%           43.2%
       481x508 owner      268    0%     39.7%         54.9%           43.2%
       820x1180 tablet    480    0%     29.1%         59.6%           43.2%
       1440x900           474    0%     39.7%         54.9%           43.2%
     The phone and the tablet keep the exact column they had (392 and 480), so both are
     untouched — the ceiling below is what holds them there.

     THE GUTTERS ARE NOT A CHOICE, they are arithmetic. Matching the phone's proportions
     on a 481x508 window needs a 268px column; filling all 481px would need the artboard
     at --u 1.303, which makes the page 938px tall — and body.home is height:100svh with
     overflow:hidden, deliberately, so it cannot scroll. Wider-than-tall means side
     margin. body.home carries the navy behind them so it reads as a framed layout
     rather than a phone stranded on white. */
  /* ---------- THE FRAME AND THE ARTBOARD ARE NOW TWO DIFFERENT THINGS, 30-08 (b) ----
     Owner: "i really like the larger view on today's catch, but on the homepage it's
     still too small. i want the width to be consistent, it's very important... note
     even if it's a bit small i really like the current view."

     THE DEFECT, measured. Every other screen in this product is a flat 480px column
     (.site, max-width:--max, --max:480px in OB-TOKENS). Home was the ONLY one that
     derived its column from the window HEIGHT -- --max was min(480, 369*h/700) -- so
     in the 980x756 window he reviews in, home drew a 398px column against the app's
     480. That is not a style difference, it is an 82px step, 17%, between two screens
     one tap apart.

     WHY IT WAS TIED TO HEIGHT, and the tie was real: --max and --u were THE SAME
     NUMBER. The artboard is 369 points wide and 700 points tall at full squeeze, so
     asking for a 480 column asked for a 910px-tall page inside 756px of a screen that
     is height:100svh, overflow:hidden and deliberately cannot scroll. That is the
     arithmetic the note above calls "not a choice", and none of it has changed.

     WHAT CHANGED is that the column no longer has to BE the artboard. Everything on
     this screen that reads as "the width" -- the type column (.hero .art), the CTA,
     the cards, the navy field, the sea -- ALREADY sizes off min(100vw, --max), i.e.
     off the FRAME, and carries only its insets in --u. So the frame can be the flat
     480 the rest of the app uses while the artboard keeps scaling to whatever the
     height allows. He gave the permission that makes this the right trade: "even if
     it's a bit small i really like the current view" -- the drawn size is acceptable,
     the frame is what he is asking for.

     ONE THING GENUINELY COUPLES THEM: the plate band. It is full-bleed and aspect-
     locked (height = width / 2.0458) and the note on .hero .plate rules out cropping
     it, squashing it, and any --plate-os below 1 -- so a wider frame IS a taller band,
     and the band eats the hero. That is the whole reason --u, --sq and --st below stop
     assuming the band is 369/2.0458 = 180.36u tall and take its real height instead:

       --u   the old `h/700` branch IS `(h - 180.36u)/519.64`. Written against the real
             band height it becomes (h - --pb)/519.64 -- the same expression with one
             assumption removed. 519.64 = 700 - 369/2.0458 = everything that is not band.
             (Only the height branch reads that literal, and phones never take it.)
       --sq  was `801u - h`: how much taller the artboard is than the screen. The
             artboard is now 801u PLUS however far the band overgrew its nominal, so
             that excess (--pex) is added. --st is the same correction, sign flipped.

     All three reduce to their previous form, term for term, when the frame is 369u
     wide -- which is every phone in portrait at 19.5:9 or taller. Not asserted,
     checked: at 392x760 the frame (392), --u (1.0623), --sq and --st all compute
     bit-identical to the old rule. Phones do not move.

       height-bound branch: pb = h - 519.64u  ->  pex = h - 700u  ->  sq = 101u exactly
                                                                  ->  st = 0
       width-bound branch : pb = 369u/2.0458  ->  pex = 0 EXACTLY ->  the old formulas

     --pex is written `--pb - 369*u/2.0458` and not against a rounded 180.36 for that
     second line alone: at 180.36 the residue is 1/64 of a pixel, which moved the CTA's
     `top` by 0.008px on eight phone viewports. Invisible, but it is the difference
     between "phones do not move" being a measurement and being a claim.

     THE FRAME'S OWN CEILING is 369*h/580 -- the same shape as the old 369*h/700, with
     the divisor the wider band earns. Solving the fit for k (the frame as a multiple
     of the artboard's own 369-point column) gives D(k) = (519.64 + 180.36k)/k, and
     k = 1.30 lands on 580. It reaches the full 480 at h >= 755 -- his window is 756 --
     and BELOW that it tapers instead of letting the band swell into the 72%-of-hero
     failure the note above was written to fix. Measured plate/hero at the floor:
     39.7% before, 46.1% after. The band is bigger because the picture is bigger; it
     is not cropped, stretched or squashed anywhere.

     WHAT IT COSTS, measured. At his window (980x756): frame 398 -> 480 (+20.6%), the
     drawing and the type 7% smaller, and the squeeze is UNCHANGED -- the old and the
     new rule both sit exactly on the 101u floor there, so no gap loses a pixel it had.
     At 1440x900 nothing perceptible moves (frame 474 -> 480, --u -0.4%).
     On his own phone at 392x656 it is a straight gain both ways: the frame goes
     346 -> 392, which closes the 23px of navy down each side that doc 003 was written
     to attack, and costs 4.6% of drawn size. At 392x760 and taller, zero change. */
  --max:min(100vw, 480px, calc(369 * var(--h) / 580));
  /* --plate-os moved up here from .hero, 30-08 (b). Its note there says it must live
     on the plate's and the fisherman's common ancestor; .site is that ancestor one
     level higher, and the vertical budget above now depends on it too, so keeping it
     on .hero would leave --pb reading a stale 1.00 the moment anyone retunes it. */
  --plate-os:1.00;
  /* the band's REAL height, and how far that is over its 369-column nominal */
  --pb:calc(min(100vw, var(--max)) * var(--plate-os) / 2.0458);
  --pex:calc(var(--pb) - 369 * var(--u) / 2.0458);
  --u:min( min(100vw, var(--max)) / 369, calc((var(--h) - var(--pb)) / 519.64) );
  --sq:max(0px, calc(801 * var(--u) - var(--h) + var(--pex)));
  /* --st is --sq's missing other half. --sq measures how much SHORTER than the 801u
     artboard the screen is, and every art offset in OB-HOME subtracts a coefficient of
     it — burger 0, wordmark .32, headline .505, CTA 1 — a depth gradient, each element
     moving up in proportion to how far down the artboard it sits. Nothing measured the
     opposite case, so on a screen TALLER than the artboard the entire surplus opened as
     ONE gap between the top-anchored group (type, mountains) and the bottom-anchored one
     (plate, wave, and the fisherman who derives from the plate).
     That is not a rounding error. At 488x1540 --u pins to the 480px width cap, so the
     artboard is 801 x 1.301 = 1042px inside 1540px of screen: 498px unaccounted, which
     rendered as 172px of dead navy under the CTA and pulled the layers far enough apart
     that they stopped overlapping. Owner: "there's too much blue space under the Let's
     Go fishing… it should be, like, a collage of pictures."
     Both clamp at 0, so exactly one is ever non-zero: a rule can carry `- k*sq + k*st`
     and only one term can fire. Every phone has st:0 and is untouched by construction. */
  --st:min( calc(63.5 * var(--u)), max(0px, calc(var(--h) - 801 * var(--u) - var(--pex))) )}

/* ---------- hero: 369 x 556.5 ---------- */
/* sampled off the handoff render at nine points: a near-flat deep navy, not a
   strong gradient. The grey noise an earlier pass produced was /x31 — that image
   is a soft MASK, not the background. */
/* 2026-08-11: retuned onto the PHOTO's own navy. Sampled off home-plate-cut itself,
   its top 4 rows average #050f54; the hero's bottom stop was #041464 — blue channel
   84 against 100 — so the two navies met in a visible band right where the picture is
   supposed to dissolve into the hero. The ramp keeps its shape (the same near-flat
   158deg sampled at nine points) scaled to land exactly on the photo at 100%. */
/* --plate-os lives HERE, not on .hero .plate, because .hero .fisher derives its own
   height from the band's height and the two are SIBLINGS — a custom property set on
   the plate never reaches the fisherman, so he silently fell back to a stale literal
   and the two disagreed about where the band's top edge was the moment this was
   retuned. Their only common ancestor is this rule. */
/* 2026-08-30, owner: "make the plate a bit smaller so we can make the logo more
   pronounced." 1.07 -> 1.00, and 1.00 is the FLOOR, not a preference. The band is
   full-bleed in width and aspect-locked in height, so its only size control is this
   multiplier — and below 1 the photo is narrower than the screen. Its left and right
   edges are hard cuts with no alpha (sampled mid-left #6f89b4, mid-right #582307), so
   any value under 1 opens a navy strip down both sides of the picture.
   Cropping it shorter instead is also out: the top of home-plate-cut is not a navy
   band but an ALPHA FADE (row 0 is fully transparent, ~0.35 by row 28, ~0.70 by row 80
   of 349), so an object-fit:cover crop would cut the fade mid-ramp and leave a hard
   semi-transparent edge where the design has a dissolve. Squashing it is what doc 003
   already tried and the owner rejected.
   The band loses 6.5% of its height (205 -> 192px at 392x760), and the fisherman takes
   every pixel of it back automatically: his height is derived from the band's top edge
   below, so shrinking the plate grows the logo without a second number to keep in step. */
/* 2026-08-30: a painted sky was tried here as a first background layer over this ramp,
   and REVERTED at the owner's word — "it's too much… let's switch back to the blue".
   The ramp below is the whole background again. Keep it that way unless a replacement
   image is actually approved: this gradient is not decoration, its last stop (#050f54)
   was sampled off the plate photo's own top rows so the picture dissolves into the hero
   instead of meeting it at a seam, and any image laid over it breaks that match by
   construction. */
/* max-height, 2026-08-30. .hero is flex:1 1 auto, so on a screen taller than the
   artboard it swallowed EVERY surplus pixel and became a long navy strip with the scene
   stranded at the bottom — owner: "i don't want that long display on mobile, it must
   feel like it's the height of just one image". 620u caps it at the artboard's own hero
   (556.5u) plus 63.5u of give, and --st above is clamped to exactly that 63.5u so the
   scene can never travel further than the hero actually grew.
   The surplus below is WHITE, not navy, and that is the honest outcome rather than a
   bug: .cards cannot absorb it (.svc.navy is a fixed 146.25u box with its icon, label
   and arrow all absolutely positioned inside), so a genuinely over-tall window simply
   ends early. No phone reaches this — at 392x760 the hero is 499px against a 659px cap. */
.hero{position:relative;z-index:2;flex:1 1 auto;min-height:0;overflow:hidden;
  max-height:calc(620 * var(--u));
  background:linear-gradient(158deg,#06105a 0%,#051261 38%,#031159 72%,#050f54 100%)}
/* The artboard's 369-wide CONTENT column — wordmark, fisherman, headline, CTA —
   centred inside a hero that runs the full width of the screen. On a screen taller
   than 1:2.17 this is the whole width and nothing moves; on a shorter one --u is
   height-bound, the column is narrower than the screen, and this keeps the type off
   the left edge while the navy, sea, plate and wave still bleed edge to edge.

   `left: calc(50% - 184.5u)` and NOT `left:50% + translateX(-50%)`: a transform would
   create a stacking context, which would trap the fisherman's z-index:1 inside this
   wrapper and float him in front of the plate that is supposed to cover his legs.
   position:absolute with z-index:auto creates no stacking context, so the children
   keep competing in the hero's own layer order exactly as before. */
/* 2026-08-11: the column now runs the FULL width, same as .cards. Owner drew a line
   straight down the left edge through the headline, the CTA and the first card: they
   must share one edge. While the column was 369u the type sat at (screen-369u)/2 +
   21.75u — 43.5px against the cards' 12.6px at 392 wide, a 31px step down that edge.
   Children below are re-anchored to the column, not re-centred inside it:
     wordmark  centred (it reads as a centred lockup, not a left-aligned one)
     h1 / cta  13.5u — the cards' own inset, so all three land on one line
     fisher    right:0 — he ended flush at x369 in the artboard, i.e. the right edge */
.hero .art{position:absolute;top:0;bottom:0;
  left:calc(50% - min(100vw, var(--max)) / 2);width:min(100vw, var(--max))}
/* the handoff's sea: a wave-edged #00105f fill at 18% (/x15 under /a2) with a
   #21479c 1.5pt shoreline stroke at 17% (/a3) above it. Both are PATHS with
   exact control points, not the vertical fade an earlier pass approximated —
   the fade had no wave edge and ran to 80%, four times too dark. */
/* height:100% rather than 556.5u — with the squeeze the hero is shorter than
   556.5u, and a fixed height would push the shoreline stroke out of the clip.
   preserveAspectRatio="none" is already on the element, so it stretches. */
.hero .sea{position:absolute;z-index:0;left:0;top:0;width:100%;
  height:100%;display:block;pointer-events:none}
/* Home's burger. Sits on the SAME left edge as the headline, the CTA and the cards
   (13.5u — see .hero .art), so the page still has one left edge. Tracks the wordmark's
   own squeeze coefficient (.32) rather than a constant, or it would drift away from
   the lockup as the screen squares off. 44u square is the touch target; the 27px glyph
   centres inside it, so the icon stays optically small while the hit area stays a
   thumb. z-index 4 — above the plate (2) and the type (3), since it must stay tappable
   whatever the band does. */
.hero .hburger{position:absolute;z-index:4;left:calc(13.5 * var(--u));
  top:calc(52.5 * var(--u) - .32 * var(--sq));
  width:calc(44 * var(--u));height:calc(44 * var(--u));
  display:flex;align-items:center;justify-content:center;
  margin:0;padding:0;border:0;background:none;color:#fff;cursor:pointer;-webkit-tap-highlight-color:transparent}
.hero .hburger svg{width:calc(27 * var(--u));height:calc(27 * var(--u));display:block}
body.home .hero .hburger:focus-visible{
  outline:calc(2.5 * var(--u)) solid #00d0ff;outline-offset:calc(2.5 * var(--u));border-radius:calc(8 * var(--u))}
/* Islands on the horizon. A 1254-square canvas that is 95% empty: the ink sits in a
   band from 36.8% to 72.6% down, with its waterline — the densest row in the file — at
   58.5%. Everything below is layout arithmetic off those three measured numbers.

   WIDTH AND HEIGHT ARE SET INDEPENDENTLY — the canvas is square and this is not. Two
   requirements pull opposite ways: the range must run off both edges ("the rest must
   be off screen… a horizon has no ends") while being SHORT ("too big… just slightly
   noticeable behind the text and button, never overlap with the logo that much").
   Scaling a square uniformly cannot do both — wide enough to bleed is tall enough to
   climb into the wordmark, which is the version that was rejected. So: 600u wide, 408u
   tall. The horizontal stretch flattens the peaks, which is what a distant horizon
   does anyway.

   `top` is solved, not eyeballed: 34.3u puts the ink's first row (36.8% of 408) at
   125px on a 392x656 phone — clear of the wordmark row, which ends at 90 — and its
   last row at 262px, which is the CTA's bottom edge. So the band spans the headline
   AND the button and stops, instead of reaching the logo. It carries the HEADLINE's
   own .505 squeeze coefficient rather than a constant, so on a squarer screen the
   islands and the words they sit behind compress together instead of sliding apart.

   z-index 0 puts it under everything — the fisherman (1), the plate (2) and the type
   (3) — so the sea lines that run down past the horizon are hidden behind the plate
   rather than crossing it. The ink is near-white (224,224,224) at up to full alpha,
   which is far too strong at this size on navy; .38 is what makes it read as haze. */
.hero .horizon{position:absolute;z-index:0;pointer-events:none;
  /* The asset's tallest peak sits ~42% across its own canvas, so on an element that
     bleeds off both edges the OFFSET places the summit and the WIDTH sets how far the
     range runs. Both moved together here (owner: "move the image more left and make it
     a bit bigger, it can grow even to the hamburger"): 600->750u wide, 408->510u tall,
     -150->-231u so the summit lands at ~79px rather than ~96.

     `top` -53.5u puts the ink's first row level with the hamburger instead of stopping
     65px below it. That is now allowed, and it does NOT contradict the earlier "never
     overlap the logo that much": that was the WORDMARK, which is centred at x130..262,
     and the peaks reaching this high are at x<170 — to its left. Checked, not assumed.

     2026-08-30, owner: "move the mountain a tad to the left so its peak is under the
     hamburger". -231 -> -275u. Measured, not nudged: thresholding the asset's alpha at
     45% (raw alpha has faint strays that put the apparent summit in the wrong column)
     the topmost solid ink row is 461 at x480-540, so the summit sits at x~505 of 1254,
     i.e. 40.3% across — near the "~42%" this note already claimed, but not the same.
     At -231u that drew the peak at x75 on a 392 phone. The target is the burger GLYPH's
     centre, x38 — NOT the 28.7 that left:13.5u + half of a 27u svg predicts: the button
     carries padding, so its box measures x14..61 and the glyph inside it x23..52. Taking
     the arithmetic on trust here lands the summit 9px left of the mark, which is how the
     first pass at this went. 75 -> 38 is 37px = 35u, so -231 - 35 = -266u.

     these four numbers came BACK after a round trip, owner: "roll back to the
     mountain and the bird separate". For a while the layer carried a single combined
     drawing (mountains + water + gulls on one canvas), which forced the framing to be
     rebuilt twice — first slid left to -320u to catch the flock, then abandoned as a crop
     altogether (left:0/width:100%) because the summit and the gulls sit at opposite ends
     of that canvas and a half-canvas window could hold one or the other. Splitting the
     birds back out removes the conflict, so the original oversized bleeding crop is
     right again and .gulls below is placed independently. */
  left:calc(-266 * var(--u));
  top:calc(-53.5 * var(--u) - .505 * var(--sq) + 1 * var(--st));
  width:calc(750 * var(--u));height:calc(510 * var(--u));
  object-fit:fill;opacity:.25}
/* wordmark: the handoff draws it x30 y52.5 at 311.25 x 97.5 — nearly the full width,
   because on the artboard it is the whole brand statement. Owner 2026-08-11: "get the
   wording of the logo same size as the other pages towards the left." So it now
   matches .site-head .logo (150x34 CSS px) and sits BESIDE the burger as a header
   lockup rather than centred as a hero mark:
     box     160 x 44u, object-fit:contain, CENTRED
   Fitting by HEIGHT inside a box the burger's own height is what puts the two on one
   optical row without hand-tuning a second top value.
   Centred, not left-aligned (owner, same session: "keep the writing center") — which
   is also what .site-head does: it is justify-content:center with the burger taken out
   of flow at the left, so home now reads identically to every other document's header.
   This frees the whole right half of the hero, which .hero .fisher now grows into. */
/* --wm scales that box, and ONLY that box (owner 2026-08-11: "on bigger screen I feel
   the logo is undervalued… the mobile should remain as is"). 1 on every phone; see the
   media query at the end of this block for the larger-screen value and the reasoning.
   The box fits the artwork by HEIGHT (image aspect 3.192, box aspect 3.636), so --wm
   reads as "how much taller the lockup is" and the width follows.
   The third term keeps the box's vertical CENTRE on 74.5u - .32sq whatever --wm is:
   centre = top + height/2 = 52.5u - .32sq - 22u(--wm - 1) + 22u(--wm). Growing from the
   centre is what keeps the wordmark on the burger's optical row — grown from the top
   edge instead, a 1.3 lockup drops 13px below the burger and the two stop reading as
   one header. */
/* 2026-08-30: 1 -> 1.15 on the phone too. "the mobile should remain as is" was the
   answer to a DIFFERENT question (doc 105, 2026-08-11: should the desktop mark grow);
   this pass is the owner asking for the mark to carry more weight on the screen he is
   actually looking at. 1.15 is what the headroom allows: the box grows from its centre,
   so it spends 3.5px upward at 392x760 and still leaves 23px of navy above the lockup,
   and the gap down to the headline only closes from 50 to 47px. */
.hero .wordmark{position:absolute;z-index:3;--wm:1.15;
  left:calc(50% - 80 * var(--u) * var(--wm));
  top:calc(52.5 * var(--u) - .32 * var(--sq) - (var(--wm) - 1) * 22 * var(--u));
  width:calc(160 * var(--u) * var(--wm));height:calc(44 * var(--u) * var(--wm));
  object-fit:contain;object-position:center}
/* gulls: their own layer. The handoff baked them into the fisherman artwork; the clean
   drawing that replaced it on 30-08 has none, and the owner's combined mountain drawing
   that briefly carried them is rolled back — so they are a layer of their own, which is
   the arrangement that actually behaves: placed and dimmed independently of both the
   range behind them and the fisherman in front.
   Owner circled the patch of navy right of the wordmark and above the fisherman's hat —
   "put some birds on the side" — and that is the only real gap in the sky: the wordmark
   holds the top centre, the headline the left, and he holds the right from his hat down.
   107u clears the wordmark, which ends at y77 on a 392 phone; at 56u they sat on it.
   Right-anchored on 12u, the SAME edge the fisherman uses, so the two read as one group.
   Artwork is dark line art on transparent, inverted to white here for the house style.
   .32 of the squeeze is the WORDMARK's coefficient, not the fisherman's .45 — these sit
   on the wordmark's row and must hold that relationship as the screen squares off.
   .38 sits between the range's .18 and the fisherman's opacity: far / mid / near. */
.hero .gulls{position:absolute;z-index:1;right:calc(12 * var(--u));
  top:calc(107 * var(--u) - .32 * var(--sq) + 1 * var(--st));
  width:calc(132 * var(--u));height:auto;opacity:.5}
/* fisherman: x153.75 y135, 215.25 x 255 — the gulls were baked into the artwork */
/* 2026-08-30, owner: "here is the clean logo use it". scene-fisherman is now the
   supplied line drawing, re-cut from oceanbasket-fisherman-illustration-transparent
   (4476x3914 -> trimmed to ink -> 900x762, white ink on alpha, stored graya like the
   file it replaces so the weight is unchanged: 133 KB PNG / 94 KB WebP).

   TWO THINGS ABOUT THE NEW DRAWING CHANGE THIS BOX, and neither is a preference:
   1. IT IS LANDSCAPE. The old art was 574x680 (0.844); this is 900x762 (1.181). The
      box fits by `contain`, so at the old 215.25u width the drawing fitted by WIDTH
      instead of by height and the man rendered 194px tall against his old 258 — the
      swap alone made the logo 25% SMALLER, which is the opposite of what the same
      session had just asked for. Width raised 215.25 -> 240u to buy it back.
   2. THE MAN IS A SMALLER PART OF IT. The trap and pole sprawl left where the old
      drawing was mostly figure, so every pixel of the man costs ~2.4 of width to the
      left. 240u is where that runs out: the trap's left tip reaches the "e" of
      "table" and stops. Measured at 392x760 — 275u puts the trap through "your" and
      300u through "our seas to", and the headline stops being readable. The man
      still lands ~12% shorter than the old artwork drew him; that is the price of
      this composition, not a number left on the table.
   The gulls are gone with the old file — they were baked into that artwork and the
   clean drawing has none. Nothing else referenced them.

   KNOCK-ON, both measured: a landscape drawing in this box fits by WIDTH nearly
   everywhere (the box only goes height-bound below about 203u of height, i.e. on a
   short window like 482x552), so --fisher-rise below now bites only there and moves
   nothing on a tall screen. And the wordmark collision this block's media query
   documents is GONE: at 1440x900 the drawing bottom-aligns to y127..389 against the
   lockup's y16..92, where the old portrait art reached up into it. */
/* HE IS THE LOGO AND MUST NEVER BE CLIPPED (owner, 2026-08-11). The handoff already
   overlaps him 9u under the plate, and the squeeze made it far worse: the plate top
   carries coefficient 1 while he carries .45, so the plate CLIMBS INTO him as the
   screen squares off — measured 64.5u, a quarter of him, at 392x656 on the 700 floor.
   Height is therefore capped to the space between his own top and the plate top:
     plate top   = 381u - 1.00*sq
     his top     = 135u - 0.45*sq
     available   = 246u - 0.55*sq
   `object-fit:contain` then scales the whole drawing down to fit, so he is complete at
   every viewport instead of being cut off at the ankles. Costs 9u of his height at the
   artboard (255 -> 246, 3.5%) because that 9u was the handoff's own overlap.

   Re-derived once the plate became bottom-anchored: its top is no longer 381u - sq but
   `hero height - band height`, so the cap is measured off the containing block instead
   of off the artboard. `.hero .art` is top:0;bottom:0, so 100% here IS the hero's
   height, and the expression tracks the plate at any viewport with no constant to keep
   in step. */
/* OVERLAP IS NOW EXPLICIT, owner 2026-08-11: "ignore that rule of not hiding the logo…
   the plate can hide a little of its foot". Left at full 255u he is simply taller than
   the space above the raised band and 47% of him disappears — legs, not feet. So the
   height is derived to land his soles exactly --fisher-dip BELOW the band's top edge:
   drawn bottom = his top + his height, so setting height to (band top - his top + dip)
   makes the hidden part exactly `dip`, at every viewport, whatever the band does.
   30u ~= 28px on a 392 phone: the soles and nothing above them.

   2026-08-30: 30 -> 0, owner: "move the fisherman slightly more up so that we can see
   its feet given there is more space now". The 2026-08-11 permission to hide a little
   of his foot was granted against a plate band that was 8% taller (--plate-os 1.07) and
   a fisherman drawn from the OLD portrait artwork; both have changed under it, and the
   band no longer needs to eat him. At 0 his soles land exactly ON the band's top edge
   rather than 30u inside it, which is where the plate's own alpha fade begins — so the
   feet read against navy, not through a 35%-opaque wash of photo.
   NOTE this moves him UP without shrinking him: he is width-bound now (the landscape
   drawing fits the 240u box by width at 255x216), so the box losing 30u of height only
   moves its bottom edge, never the drawn size. */
/* --fisher-rise lifts his TOP edge without moving his soles, which is the only direction
   he can grow (owner 2026-08-11: "fisherman logo still small"). Because the height below
   is `space above the band - his top`, raising the top ADDS exactly that much height, so
   one variable does both and his soles stay --fisher-dip below the band's top edge.
   0 on a phone; see the media query at the end of this block.

   --fisher-top exists so the top edge is written ONCE. The expression was already spelled
   out twice — in `top` and inside `height` — and a third copy for the rise is how these
   two silently disagree about where he starts.

   object-position:bottom, not the default centre: with a rise he can now reach his full
   natural size, and the moment the box is TALLER than the artwork `contain` centres the
   drawing and floats his soles up off the band, opening a gap the design has never had.
   Bottom-aligned, the slack all lands above his head and the growth simply stops when he
   is complete. */
/* 2026-08-30, third and last placement move: owner drew an arrow off the hat to a mark
   up and to the RIGHT — "I want that man there". Both axes had to move together, and
   they fight each other: he is right-anchored and width-bound, so GROWING him raises his
   head (soles are pinned to the band) but slides it LEFT, because his head sits ~61%
   across a canvas whose right edge is fixed. Growing alone would have taken the head to
   x249 when the mark was x302. So width 231 -> 289u for the height, and the anchor
   12u -> -38u to put it back on the mark. Landed x299/y143 against a mark of ~302/132.
   THE POLE IS NOW CLIPPED, 39px off the right edge, and that is deliberate. It does not
   reopen the 2026-08-11 "he must never be clipped" rule: that was about the MAN losing
   his legs to the plate, and he is whole here — it is the tip of the pole he carries
   that leaves the frame, which reads as the frame ending, not as damage. */
.hero .fisher{position:absolute;z-index:1;right:calc(-38 * var(--u));--fisher-dip:0;--fisher-rise:0;
  --fisher-top:calc(115 * var(--u) - .45 * var(--sq) - var(--fisher-rise) * var(--u));
  top:var(--fisher-top);
  /* 2026-08-30, in two moves. First 240 -> 178u to place him: owner drew a vertical at
     x307, "I want most of his body to be right here in this space", size fine "maybe
     even a little smaller". Then 178 -> 231u: owner drew an arrow from his hat straight
     up to y100 — "grow the image a bit more" — which also settles what "it must touch
     the logo or the bird" meant. TOUCHING IS THE POINT, not a collision to dodge; at
     y100 his head is inside the flock's band (y85-143) and that is deliberate.

     SOLVED, not nudged. He is width-bound and right-anchored on 12u with his soles
     pinned to the band top at y308, so width alone sets his height and every edge:
       drawn height = 308 - 100 = 208  ->  width = 208 * 1.181 = 246px = 231u
     What it costs, stated plainly: the trap's left edge lands at 379.3 - 246 = x133
     against a headline ending at x183, so it crosses "your table" by 50px. That is the
     standing trade of this landscape drawing — the man is the right third of the canvas
     and the trap is the rest, so every pixel of man costs ~2.4 of width to the left.
     The owner has now chosen the man twice over the clearance. */
  /* 289 -> 240u, 30-08: owner — "make the fisherman slightly smaller, just a little bit
     so the back of the image doesn't overlap". The back is the trap, and the overlap is
     with the headline: measured at 392x760 the drawing's left edge ran to x145 against a
     headline ending at x184, i.e. 39px across the type. 240u puts the edge at x177 and
     the overlap at 6px — the net's outermost line grazing the text edge, not crossing it.
     Full clearance is ~232u, but that costs another 8u of him for 6px nobody can see. */
  width:calc(240 * var(--u));
  height:max(70 * var(--u),
             calc(100% - min(100vw, var(--max)) * var(--plate-os) / 2.0458
             - var(--fisher-top)
             + var(--fisher-dip) * var(--u)));object-fit:contain;object-position:bottom;
  /* 2026-08-30, owner: "the logo is too in your face, can you make its opacity a little
     lower but still higher than that of the mountain to give the perception of depth.
     mountain is perfect though." So this is a DEPTH STACK, not a brightness setting, and
     the three values are only meaningful against each other:
         .hero .horizon  .18   far     — owner-approved, do not touch
         .hero .fisher   .45   middle  — this line
         wordmark / h1 / cta  1.0  front
     .45 is 2.5x the mountain, which is what keeps him unambiguously in front of it, and
     low enough that the white line work stops competing with the headline. .6 was tried
     and still reads as foreground.
     ⚠ THIS NUMBER IS PAIRED WITH THE MOUNTAIN ARTWORK. It was briefly .8, because the
     combined drawing that carried the gulls reads far stronger at the same .18 and he
     dissolved into it at .45. That drawing is rolled back, so .45 is right again — but
     if the range behind him ever gets heavier, expect to move this with it. */
  opacity:.75}
/* headline: Inter ExtraBold 29.25pt, left 21.75, BASELINES 205.5 / 240.75 /
   276.75 (the Tm/Td operators, not the 276 an earlier pass recorded — the
   second Td is -1.230769em = 36pt, where the first is -1.205128em = 35.25pt).

   Inter's font box is 1.20996em, so with a 35.25 line box the first baseline
   sits at top - 0.0705 + 0.96875*29.25; solving for baseline 205.5 puts the
   block at 177.25, not the 172 that was here.

   TRACKING: the handoff's TJ arrays carry ~31/1000 em on nearly every pair on
   top of the real kerns, so the headline is set TIGHT. -.028em reproduces all
   seven word extents to within 0.64pt; the -.005em that was here left the
   three lines 6.6-7.4pt too wide. Nothing else on the page is tracked — the
   card and button strings match Inter's own metrics exactly, which is also the
   proof that Inter is the right face. */
/* 2026-08-11, owner: "the main text can go a little higher and maybe even a tad
   bigger." 177.25 -> 160u and 29.25 -> 31pt, with the line box moved in step
   (35.25 -> 37.35, the same 1.2051 ratio the handoff uses) so the three lines keep
   their drawn rhythm instead of the leading opening up under a larger face.
   This is the first DELIBERATE departure from the handoff's type metrics — the
   baselines above were solved off the PDF's own Tm/Td operators, and 160/31/37.35 are
   not those numbers. Kept the -.028em tracking, which is what makes the three lines
   measure correctly; dropping it would widen them ~6% on top of the size change. */
.hero h1{position:absolute;z-index:3;left:calc(13.5 * var(--u));
  top:calc(160 * var(--u) - .505 * var(--sq) + 1 * var(--st));
  margin:0;font-family:var(--sans-hero);font-weight:800;color:#fff;
  font-size:calc(31 * var(--u));line-height:calc(37.35 * var(--u));letter-spacing:-.028em}
.hero h1 span{display:block;white-space:nowrap}
.hero h1 .l2 em{font-style:normal;color:#00aee9}
/* line 3 is 36pt below line 2 where line 2 is 35.25 below line 1. Reproduced as
   drawn; it is almost certainly a slip. Delete this rule to put it on the grid. */
.hero h1 .l3{color:#00aee9;position:relative;top:calc(.75 * var(--u))}
/* CTA pill: x21.75 y345, 183 x 36. Its path's corner beziers give a RADIUS OF
   12.75, not the 18 a fully-round pill would have — 999px was wrong at both
   ends. Fill is /sh24, a horizontal axial from #0aa8df to #00c1ef whose axis
   starts 16.92 into the pill and runs on past it, so the pill only ever shows
   the first half: flat #0aa8df for 9.25%, then to #05b5e7 at the right edge.
   Label Inter SemiBold 15pt, baseline 368.25, from x35.25. */
/* 1 here and 0 on the plate below MUST SUM TO 1. The handoff's own rule is "CTA
   bottom == plate top" (both y=381); the CTA is top-anchored and the plate is
   bottom-anchored, so the two shares of the squeeze have to account for all of it or
   the two edges drift apart. The plate is exempt (see below), so the CTA carries all
   of it. Measured: |ctaBottom - plateTop| is 0.02-0.03px at every viewport tested,
   landscape included. */
.hero .cta{position:absolute;z-index:3;left:calc(13.5 * var(--u));
  top:calc(345 * var(--u) - 1 * var(--sq) + 1 * var(--st));
  width:calc(183 * var(--u));height:calc(36 * var(--u));border-radius:calc(12.75 * var(--u));
  background:#fff;
  display:flex;align-items:center;padding-left:calc(13.5 * var(--u));box-sizing:border-box;
  font-family:var(--sans-hero);font-weight:600;font-size:calc(15 * var(--u));
  /* 2026-08-30, owner: "let's try these button style" — the pill inverts to white with
     navy type, and .svc.navy .go inverts with it (see there).

     THIS CLOSES THE CONTRAST GAP THIS COMMENT USED TO HOLD OPEN. The note that stood
     here recorded the primary action failing WCAG AA and said so plainly: white on the
     cyan gradient measures 2.73:1 at the dark end and 2.39:1 at the light one, against
     a 4.5:1 requirement, and the only fix that did not change the look was a darker
     pill, costed in doc 002 sect 4. That is now moot — #07126e on #fff measures
     15.9:1, so the change the owner asked for on looks also happens to be the one the
     accessibility note was asking for. The cyan is not lost: it is still the hero's
     accent on the focus ring and the .svc.navy icon. */
  color:#07126e;text-decoration:none;white-space:nowrap}
/* the arrow's viewBox IS the pill, so it carries the handoff's own coordinates
   (x177->191.25 on y362.25, 1.8pt round) instead of a generic 24-unit glyph
   nudged into place — the generic one came out 2.4pt short and 1.9pt left. */
/* baseline 368.25; flex-centring a 15pt line inside the 36 pill lands it 1 low */
.hero .cta .lbl{position:relative;top:calc(-1 * var(--u))}
.hero .cta .ar{position:absolute;left:0;top:0;width:100%;height:100%;display:block}
.hero .cta .ar svg{width:100%;height:100%;display:block;
  stroke:#07126e;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* plate: x0 y381, 369 x 175.5, drawn `369 0 0 -175.5 0 556.5 cm` — the image is
   478x234 and the box is 369x175.5, so the handoff STRETCHES it. `contain`
   letterboxed it 5.2 either side and shrank the food by 3%.

   These last two are placed from the BOTTOM even though the artboard gives
   them top coordinates. The artboard's hero is 556.5 and this one is 555.75 —
   the cards overlap it by .75 — and more importantly the hero FLEXES: on a
   short screen it gives up height, and a top-anchored plate would slide out
   from under the clip and vanish. Bottom + the .75 makes both true at once. */
/* THE PLATE IS EXEMPT FROM THE SQUEEZE. Its coefficient is 0 and object-fit stays
   `fill` — this is the handoff's own placement (`369 0 0 -175.5 0 556.5 cm` on a
   478x234 image; our asset is that same image at 2x, RMSE 1.5%) and it must not be
   touched at any viewport.

   A first pass at doc 003 took .28 of the squeeze here and switched to `cover`. That
   was WRONG, and worth recording why. The photo's own top band is navy and its own
   bottom is a white brush-stroke: those two edges are what dissolve the picture into
   the hero above and the white field below, so it reads as a layer floating just
   under the CTA rather than a photo in a box. `cover` crops exactly those edges off,
   and shortening the band crops more — up to 16%. The result was two hard horizontal
   cut lines where the design has none. The owner called it immediately.

   Height is bottom-anchored at full 175.5u, so the CTA carries the whole squeeze
   (coefficient 1 above) and "CTA bottom == plate top" still resolves exactly.

   TRUE ASPECT (2026-08-11, owner: "I want to see the edge a little more towards the
   bottom... so it can splash on the page rather than cut roughly"). The band is
   full-bleed in WIDTH but was fixed in HEIGHT, so the photo only kept its own aspect
   at the artboard. On a 392-wide phone it rendered 392x159.9 — aspect 2.45 against
   the asset's true 2.0458 — a 20% horizontal stretch that flattened the bottom
   brush-stroke into a straight line. That is the "rough cut": not a crop (nothing is
   cropped, object-fit stays `fill`), a squash.

   Height now derives from the rendered width, so the stroke always renders at its
   drawn proportion. The band grows DOWNWARD: the bottom offset carries the growth so
   the TOP stays on its 381u-minus-squeeze line and "CTA bottom == plate top" still
   resolves exactly, while the element stays BOTTOM-anchored for the flex reason
   above. Cost, and it is a real one: at the artboard the band is 180.64u against the
   handoff's 175.5u, so the "zero deviation at 369x801" property from doc 003 is gone.
   It has to be — the handoff itself puts a 956x468 photo in a 369x175.5 box, so
   handoff-exact and true-aspect are mutually exclusive. Owner chose the splash. */
/* 2026-08-11, owner: "move the plate a little backwards, I need to see the full front,
   the back can be hidden a bit." At true aspect the band is TALLER than the gap between
   the CTA and the hero's lower edge — 191.9 against 163.8 at 392x656 — so anchoring its
   TOP pushed 28px of the dish's near rim below the hero's overflow:hidden. The front of
   the plate, the part that sells the food, was the part being cut.
   Anchored to the hero's bottom edge instead: the whole front is above the clip, and the
   overflow moves to the TOP of the photo, which is its navy blend band and reads as
   nothing. THIS RETIRES "CTA bottom == plate top" — the CTA now sits over that navy
   band. Unavoidable: the band cannot be shorter without giving up true aspect, and the
   hero has no slack, so top-anchored and full-front are mutually exclusive.

   OVERSCAN (--plate-os), owner 2026-08-11: "move the plate a little higher… the plate
   can hide a little of its foot but the button must be fully visible". Bottom-anchored
   and aspect-locked, the only way the band's TOP rises is for the band to get BIGGER,
   and the only way it gets bigger at a fixed aspect is to be wider than the screen.
   It is drawn 8% over and centred, so it grows by 4% off each side.
   That costs nothing: the photo's LEFT and RIGHT edges are hard cuts already — sampled
   mid-left #6f89b4, mid-right #582307, no splash and no alpha on either — so the only
   drawn edges are the navy top band and the white brush-stroke bottom, and overscanning
   sideways touches neither. Raising it any other way (bottom > 0) would open a navy
   strip between the band and the wave, since the wave's own deepest point leaves only
   1.6px of cover. */
.hero .plate{position:absolute;z-index:2;
  left:calc((100% - 100% * var(--plate-os)) / 2);bottom:0;
  width:calc(100% * var(--plate-os));
  height:calc(min(100vw, var(--max)) * var(--plate-os) / 2.0458);object-fit:fill}
/* the white field enters on a shallow curve, from y531 on the left, dipping to
   539.25 mid, rising to 525.75 — so its box is y531..565, which is 9.25 below
   the hero's lower edge. Sitting it flush at bottom:-1px put it 8.25 too high. */
.hero .wave{position:absolute;z-index:3;left:0;bottom:calc(-9.25 * var(--u));width:100%;
  height:calc(34 * var(--u));display:block}

/* ---------- cards ---------- */
/* handoff: the block runs x20.25 -> 362.25 (342 wide). NOTE that is 20.25 in
   from the left and only 6.75 from the right — the block sits 6.75pt right of
   centre IN THE FILE. Reproduced as drawn; make both 13.5 to centre it. */
/* WAS the same 369-wide column as .hero .art. Owner, 2026-08-11: "the content must
   extend to that point" — out to the screen edges, not to the artboard column. When
   --u is height-bound the 369 column is NARROWER than the screen, and the leftover
   became the dead gutter he was complaining about; the cards were carrying it twice
   over (column gutter + their own 20.25/6.75 inset). They now take the full width and
   keep the handoff's symmetric-corrected 13.5 inset on both sides.
   Only WIDTH changes — the card heights below stay in u, so this steals no height
   from the hero. That was doc 003 §4's objection to full-width cards, and it does not
   apply to widening at constant height. */
.cards{position:relative;z-index:3;flex:0 0 auto;
  width:min(100vw, var(--max));margin-inline:auto;
  padding:0 calc(13.5 * var(--u)) calc(11.25 * var(--u)) calc(13.5 * var(--u));
  display:grid;grid-template-columns:1fr 1fr;column-gap:calc(10.5 * var(--u));
  row-gap:calc(12 * var(--u))}
.svc{position:relative;display:block;text-decoration:none;border-radius:calc(15 * var(--u))}
/* navy cards: 165.75 x 146.25, radius 15. Fill is /sh27 and /sh28, an axial
   from the card's top-left CORNER to its bottom-right corner: #0b1f86 ->
   #020d62. For a corner-to-corner direction CSS's gradient-line length works
   out equal to the diagonal, so 131.42deg (=90+atan(146.25/165.75)) is exact.
   The three sampled stops that were here bottomed out at #061572, well short
   of the real #020d62. */
/* overflow:hidden is load-bearing from 30-08: the icon is a watermark bled off the
   bottom-right corner, and without it the glyph paints OUTSIDE the card and over the
   white field below. Scoped to .navy so .wide, which has no bled child, keeps its own
   box untouched. */
.svc.navy{height:calc(146.25 * var(--u));overflow:hidden;
  background:linear-gradient(131.42deg,#0b1f86 0%,#020d62 100%)}
/* the icon SVGs use the CARD as their viewBox and carry the handoff's own path
   data in card-relative coordinates, so each glyph lands exactly where drawn
   rather than being re-approximated inside a small box. */
/* 2026-08-30 — WATERMARK. Owner picked this off a three-option comparison: "I like the
   big colors in the first one, and the icon placement on the third one." The glyph stops
   being a small object in the corner and becomes the card's texture — blown up to 126u,
   bled off the bottom-right, and dropped to 17%. The markup carries a tight viewBox
   (24 19 50 48) rather than the handoff's full-card one, because the handoff drew these
   in CARD-RELATIVE coordinates: at the original viewBox the glyph occupies only the
   upper-left quadrant, so scaling the box would have scaled the empty space with it. */
.svc.navy .ico{position:absolute;inset:auto calc(-14 * var(--u)) calc(-16 * var(--u)) auto;
  width:calc(126 * var(--u));height:calc(126 * var(--u));display:block}
.svc.navy .ico svg{width:100%;height:100%;stroke:#00b9f2;fill:none;stroke-width:2.6;
  opacity:.17;stroke-linecap:round;stroke-linejoin:round}
/* the plane is WHITE and the house is cyan. Not a symmetry the layout suggests,
   but the handoff's plane block sets no RG and so inherits the white left by the
   arrow drawn before it — deliberate or not, it is what the render shows. */
/* THE PAIR NOW ALTERNATES. Card 2 takes the white treatment, so the row reads
   navy / white / white instead of one weight repeated twice. The wide card below stays
   exactly as it was — owner: "the check live stock must remain white as is" — so the
   white card and the white bar sit adjacent; that is the thing to watch on a short
   screen, and it is deliberate, not an oversight.
   #7f88c7 and #07126e are the wide card's own rule and ink, reused rather than invented,
   which is what keeps the two white surfaces reading as one family. */
.svc.navy.alt{background:#fff;border:calc(1.125 * var(--u)) solid #7f88c7}
.svc.navy.alt .ico svg{stroke:#07126e;opacity:.14}
.svc.navy.alt .go{background:#07126e}
/* titles: card 1 is 16.125pt and card 2 is 14.1pt IN THE HANDOFF — the longer
   label was set smaller to fit. Both share a baseline at y651 (95.25 below the
   card) and a 20.25pt second line. Because the two sizes have different half-
   leading inside that 20.25 box, one shared `top` cannot put both on the same
   baseline: 79.25 and 80. The 72 that was here left both ~7 too high. */
/* Labels move to the TOP of the card. The watermark now owns the lower right, and the
   handoff's 79.25/80 baselines put the type straight through it. 20u keeps the two
   titles on one optical row despite their different sizes (16.125 vs 14.1), which the
   handoff's own two-value fudge was solving for at the old position. */
.svc.navy b{position:absolute;left:calc(14.25 * var(--u));top:calc(20 * var(--u));
  font-family:var(--sans-hero);font-weight:700;color:#fff;
  font-size:calc(16.125 * var(--u));line-height:calc(20.25 * var(--u))}
.svc.navy.alt b{font-size:calc(14.1 * var(--u));top:calc(20.75 * var(--u));color:#07126e}
/* round arrow: r15 centred at y672.75 = 117 below the card top */
.svc.navy .go{position:absolute;right:calc(14.25 * var(--u));top:calc(102 * var(--u));
  width:calc(30 * var(--u));height:calc(30 * var(--u));border-radius:50%;background:#fff;
  display:flex;align-items:center;justify-content:center}
/* viewBox = the disc, so these are the handoff's own coordinates: x8.25->21.75
   on y15, 1.8pt round. The generic glyph drew it 9.4 long against 13.5. */
.svc.navy .go svg{width:100%;height:100%;display:block;
  stroke:#07126e;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* .alt is the WHITE card, and it only ever overrode the disc colour — it inherited its
   glyph from the rule above. That rule is now navy, which on .alt's navy disc is an
   invisible arrow, so the pairing has to be stated on both halves rather than one:
   white surface -> navy disc, white glyph; navy surface -> white disc, navy glyph. */
.svc.navy.alt .go svg{stroke:#fff}
/* wide card: 342 x 75.75, white, 1.125pt #7f88c7 rule. The handoff `B`s the
   path — fills AND strokes it — so the rule STRADDLES the outline, 0.5625
   either side. A CSS border sits wholly inside, which drew the card 1.125
   narrower and shorter than the design.

   KNOWN, MEASURED, AND LEFT AS IS — the one value on this page that is not the
   handoff's. A CSS border cannot straddle, and both ways of faking it came out
   worse on the pixel diff: outline-offset does not place a negative edge where
   reading the spec suggests, and splitting the rule into a 0.5625 border plus a
   0.5625 shadow spread makes Chrome snap each half to a whole device pixel and
   draw 1.5pt of line instead of 1.125. Negative margins WOULD be exact, but the
   height of this grid row is what puts the hero's bottom edge at 555.75, so
   they would move the entire screen unless padding-bottom below were adjusted
   to match — a coupling not worth 0.5625pt on a hairline. */
.svc.wide{grid-column:1 / -1;height:calc(75.75 * var(--u));background:#fff;box-sizing:border-box;
  border:calc(1.125 * var(--u)) solid #7f88c7;display:flex;align-items:center}
/* disc r25.5 centred at (57.75, 751.875) — 12 in from the card edge */
.svc.wide .ico{flex:0 0 auto;margin-left:calc(10.875 * var(--u));
  width:calc(51 * var(--u));height:calc(51 * var(--u));border-radius:50%;background:#e0f5ff;
  display:flex;align-items:center;justify-content:center}
/* the shopfront's viewBox is the DISC (51 units), so it has to be drawn AT 51 —
   rendering that viewBox into a 30px box shrank the icon to 59% of the size it
   is in the handoff, which is what made this card read as under-weighted.
   Stroke is 1.8, not 2.2. */
.svc.wide .ico svg{width:100%;height:100%;display:block;
  stroke:#101a78;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* text starts at x107.25; centring the LINE BOX is not centring the ink, and
   Inter's box is bottom-heavy, so the baseline lands 1 above the handoff's 759. */
.svc.wide b{margin-left:calc(24 * var(--u));flex:1;font-family:var(--sans-hero);
  font-weight:700;color:#07126e;font-size:calc(16.875 * var(--u));line-height:1.1;
  position:relative;top:calc(1 * var(--u))}
/* x328.5->347.25 on y752.25, stroke 2.1 — 18.75 long, half again the 12.5 the
   generic glyph drew. */
.svc.wide .go{flex:0 0 auto;margin-right:calc(12.375 * var(--u));display:flex;align-items:center;
  position:relative;top:calc(.375 * var(--u))}
.svc.wide .go svg{width:calc(21.75 * var(--u));height:calc(15 * var(--u));display:block;
  stroke:#07126e;fill:none;stroke-width:2.1;stroke-linecap:round;stroke-linejoin:round}

/* Keyboard focus. Home has four links and NONE of them showed a focus ring: the
   only :focus-visible rule in either sheet targets the <summary> elements on other
   surfaces, so tabbing through this screen was invisible (WCAG 2.4.7). :focus-visible
   rather than :focus, so a tap or a click still shows nothing — no change for the
   touch users who are almost all of the traffic. The offset rings sit OUTSIDE the
   navy cards, where the cyan reads against both the white field and the hero. */
body.home .hero .cta:focus-visible,
body.home .svc:focus-visible{
  outline:calc(2.5 * var(--u)) solid #00d0ff;
  outline-offset:calc(2.5 * var(--u))}

/* One reveal, whisper-quiet. */
@keyframes ob-home-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
body.home .hero .wordmark,body.home .hero h1,body.home .hero .cta,body.home .svc{
  animation:ob-home-in .22s ease-out backwards}
body.home .hero h1{animation-delay:.05s}
body.home .hero .cta{animation-delay:.1s}
body.home .svc{animation-delay:.15s}
body.home .svc:nth-of-type(2){animation-delay:.19s}
body.home .svc:nth-of-type(3){animation-delay:.23s}
@media (prefers-reduced-motion:reduce){
  body.home .hero .wordmark,body.home .hero h1,body.home .hero .cta,body.home .svc{animation:none}
}

/* ---------- the wordmark on a screen bigger than a phone ---------- */
/* Owner 2026-08-11: "on bigger screen I feel the logo is undervalued, can we make it
   bigger for larger screen size. the mobile should remain as is."

   WHY IT LOOKS SMALL THERE, and it is not a feeling — .site is capped at --max (480px),
   so past 480 NOTHING in this design grows: --u is min(480/369, h/700) and a desktop
   window is proportionally SHORTER than a phone, so --u goes height-bound and the whole
   artboard is smaller in the column than it is on a phone. Measured drawn wordmark:
       owner's phone 392x656   131px in a 392 column   33.5% of the screen
       laptop      1280x720    145px in a 480 column   30.2%
   The brand mark is the one thing on the page that has no reason to obey the phone
   artboard on a desktop, so it — and only it — is scaled back up.

   1.3, not more. The growth is centred (see .hero .wordmark), so it spends the headroom
   above the lockup, which is 43.4 - 22.65*--wm px at 1280x720: 1.3 leaves 14px of navy
   above the mark, 1.55 leaves 8 and reads as jammed against the screen edge. Worst case
   inside this query (481x600) still leaves 11.6px, and the gap DOWN to the headline only
   closes from 46px to 39px, so nothing here can collide.

   BOTH conditions are load-bearing. min-width keeps every phone in portrait out (they are
   all narrower than the 480 cap). min-height keeps every phone in LANDSCAPE out too —
   844x390 passes the width test easily — which is what "the mobile should remain as is"
   actually requires.

   ⚠ min-height WAS 600px, and that was WRONG: the owner reviews this in a browser window
   482x552 CSS px (a 964x1104 Retina capture), so the first deploy of this rule did nothing
   at all on the screen he was looking at — his report was "still small" because it WAS
   still 1. 480px is the floor that admits his window and still excludes every phone in
   landscape: the tallest is 440 CSS px (iPhone 16 Pro Max, 956x440), and browser chrome
   only ever makes that number smaller. Measured at 482x552 with 1.3: 10.7px of navy above
   the mark, 30px of gap down to the headline.

   ---------- and the fisherman, same query ----------
   He is starved on a window this shape, and by a lot: the plate band is aspect-locked to
   the 480 column, so it is a FIXED 251px while the hero shrinks with the window — at
   482x552 the band is 70% of a 358px hero and he renders at 38% of his natural size.
   45u of rise takes him to 56% there (+46%), and to 100% — complete, for the first time on
   a desktop — from about 1280x800 up.

   THE ONE COST, measured, not guessed: at 1440x900 he reaches full size, and his head
   column (canvas x 317..564 of 574, i.e. the top fifth of the drawing is all in its right
   44% — measured off the PNG's alpha) then overlaps the wordmark's ink by 16.7px in rows
   44..91. He is z-index 1 against the wordmark's 3, so the type paints over the line work
   rather than the other way round. Lower the 45 to remove it; every 10u costs him ~4% of
   natural size on the owner's own window. The two asks genuinely compete here — a bigger
   wordmark and a bigger fisherman both want the same band of navy, and the band above the
   plate is all there is. */
@media (min-width:481px) and (min-height:480px){
  /* 2026-08-30: 1.3 -> 1.35 with the same ask as the phone above. Not further: the
     measurement in this note is a ceiling, not a starting point — the mark grows from
     its centre into the navy above it, which is 43.4 - 22.65*--wm px at 1280x720, and
     the 1.55 that "reads as jammed" is 8px. 1.35 leaves 12.8px there and 9.9px in the
     owner's own 482x552 window; 1.45 would leave 7.3 and cross the line this note drew. */
  body.home .hero .wordmark{--wm:1.35}
  body.home .hero .fisher{--fisher-rise:45}
}
/* ---------- large screens: let the artboard grow ----------
   Owner: "why is it not taking the fatter view on larger screen?" Because --max caps
   .site at 480px on every surface, and --u is min(min(100vw,--max)/369, --h/700) — so
   past 480px of width the artboard CANNOT grow, and a big window gets a phone column
   with slack around it. That is also where the leftover space comes from: measured at
   1200x1400, --max 480 -> 760 takes the hero 807 -> 910px and the slack 274px -> 0.

   Deliberately narrow in scope. HOME ONLY (body.home), so no other document's shell
   moves, and only past 1000x900 — the tablet at 820x1180 and every phone are below that
   floor and render byte-identically to what is already approved. Home carries no bottom
   nav, so widening .site here does not disturb --max's other consumer.
   If this looks right, the same rule can be lifted to :root for the whole app — that is
   a separate, app-wide decision and is NOT what this does. */
@media (min-width:1000px) and (min-height:1000px){
  /* same rule as the default, one ceiling up: a big window may grow the artboard to 760,
     but only as far as its HEIGHT can carry it, or the band swells again exactly as
     described on body.home .site. A tall desktop (1200x1400) reaches 738 and gets the
     fat view this note originally asked for; 1440x900 is height-bound to 474. */
  /* 30-08 (b): the divisor swaps to 580 like the rule above, AND this query's height
     floor goes 900 -> 1000. Both are needed; the second is the one that matters.

     LEFT ALONE, this rule fought the consistency ask that motivates the whole pass. A
     1440x900 laptop clears 1000x900, so it fired, and with the new divisor it handed
     home a 572px column while Today's catch next door is 480 -- a WIDER mismatch than
     the 398-vs-480 being fixed. The old rule got 474 there only by accident: 900px of
     height could not carry 480 under the old formula, so the 760 never actually bit.

     1000 is where the rule starts earning its keep again, and it is derived, not
     picked. Its purpose is the dead white field under the cards on an over-tall window.
     With a flat 480 frame the artboard goes width-bound above h = 911, and --st absorbs
     the first 63.5u = 82.6px of the surplus, so nothing is genuinely stranded until
     h ~= 993. Below that the flat 480 already fills the screen and growing the frame
     buys nothing but the mismatch. Measured after the change: 1440x900 and 1280x720
     both land on 480, matching the app; 1200x1400 still reaches 760 with no slack.

     STILL AN OPEN QUESTION rather than silently resolved: past 1000x1000 home is 760
     while every other screen is 480. That is an older explicit ask ("why is it not
     taking the fatter view on larger screen?") pulling against today's. Left in --
     the window under review is 756 tall and never reaches it. */
  body.home .site{--max:min(100vw, 760px, calc(369 * var(--h) / 580))}
}
/* ==== END OB-HOME ==== */

/* ==== BEGIN OB-NAV ==== */
/* The five tabs are the spine of "one app": same order, same colours, same
   height on every surface. `a` for the landing documents, `button` for the
   app's in-page router — styled together so they cannot drift apart.

   doc 105 turned the bar WHITE, with a 1.5px hairline top edge rather than a
   shadow — that part is measured off the pack and stands.

   ⚠ TWO DELIBERATE DEPARTURES FROM THE PACK, owner 2026-08-10 ("the icons are
   too small, make the navbar feel a bit more polished and easy for the UX"):

   1. SIZE. The pack draws 18px icons with 7px labels. That is a design pass on a
      375pt artboard, not a thumb on glass — Apple's own tab bars run 24-28pt
      glyphs, and 18px reads as a browser toolbar rather than an app. Icons are
      24px here and labels 10.5px, with the whole cell a ≥48px tap target.

   2. THE ACTIVE TAB TINTS ITS ICON, NOT JUST ITS LABEL. The pack keeps every
      icon pure black and colours only the active word. Both independent 300dpi
      measurement passes flagged that as a probable render defect and recommended
      tinting, and it is genuinely worse to use: the active tab is identified by
      one small word rather than by the thing the eye actually lands on. Inactive
      icons also take the muted grey instead of black, so active/inactive differ
      in weight AND colour rather than colour alone — which is what makes it
      legible at a glance and to anyone who cannot separate the two hues.

   If the pack's exact treatment is ever wanted back, it is these two rules and
   nothing else. */
.bottomnav{position:fixed;bottom:0;left:50%;transform:translateX(-50%);
  width:100%;max-width:var(--max);height:calc(var(--nav-h) + env(safe-area-inset-bottom));
  background:var(--navbar);display:flex;align-items:stretch;z-index:60;
  border-top:1.5px solid var(--navline);
  padding:0 6px env(safe-area-inset-bottom);box-sizing:border-box}
.bottomnav a,.bottomnav button{flex:1;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:4px;background:none;border:0;cursor:pointer;
  padding:6px 2px 7px;min-height:48px;
  color:var(--navoff);text-decoration:none;-webkit-tap-highlight-color:transparent;
  font-family:var(--ui);font-size:10px;font-weight:500;letter-spacing:.01em;
  transition:color .15s ease}
.bottomnav a.on,.bottomnav button.on{color:var(--navon);font-weight:700}
.bottomnav svg{width:21px;height:21px}
/* the icon inherits the cell's colour, so active/inactive is one decision */
.bottomnav .nico{display:flex;align-items:center;justify-content:center;height:21px;line-height:1;
  color:inherit;transition:transform .12s ease}
.bottomnav a:active .nico,.bottomnav button:active .nico{transform:scale(.9)}
.bottomnav .cartbadge{position:relative}
.cartbadge .cnt{position:absolute;top:-5px;right:-10px;background:var(--bad);color:#fff;
  font-size:10px;font-weight:700;min-width:18px;height:18px;border-radius:9px;
  display:flex;align-items:center;justify-content:center;padding:0 4px;
  border:2px solid var(--navbar)}
/* ==== END OB-NAV ==== */

