/* ======================================================================== */
/* DTJ. One stylesheet, six pages. Written by pages/07_contact_footer/build_site.py
   out of pages/07_contact_footer/chrome. Do not edit this file: edit the chrome
   and build again, or the next build throws the edit away. */
/* ======================================================================== */

/* The five faces are served from this site. No request leaves it, which is the
   only way the privacy claim in the contact modal is true without a footnote.
   latin and latin-ext only. DM Sans is one variable file declared three times,
   exactly as Google declares it, so it downloads once and renders unchanged.
   Paths are relative to this file, which is why they work from every page. */
/* The five faces are served from this site. No request leaves it, which is the
   only way the privacy claim in the hero modal is true without a footnote.
   latin and latin-ext only. DM Sans is one variable file declared three times,
   exactly as Google declares it, so it downloads once and renders unchanged. */
@font-face{ font-family:'Anton'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/anton-400-latinext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face{ font-family:'Anton'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/anton-400-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face{ font-family:'DM Mono'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/dmmono-400-latinext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face{ font-family:'DM Mono'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/dmmono-400-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face{ font-family:'DM Mono'; font-style:normal; font-weight:500; font-display:swap;
  src:url(../fonts/dmmono-500-latinext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face{ font-family:'DM Mono'; font-style:normal; font-weight:500; font-display:swap;
  src:url(../fonts/dmmono-500-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face{ font-family:'DM Sans'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/dmsans-var-latinext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face{ font-family:'DM Sans'; font-style:normal; font-weight:400; font-display:swap;
  src:url(../fonts/dmsans-var-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face{ font-family:'DM Sans'; font-style:normal; font-weight:500; font-display:swap;
  src:url(../fonts/dmsans-var-latinext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face{ font-family:'DM Sans'; font-style:normal; font-weight:500; font-display:swap;
  src:url(../fonts/dmsans-var-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face{ font-family:'DM Sans'; font-style:normal; font-weight:700; font-display:swap;
  src:url(../fonts/dmsans-var-latinext.woff2) format('woff2');
  unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face{ font-family:'DM Sans'; font-style:normal; font-weight:700; font-display:swap;
  src:url(../fonts/dmsans-var-latin.woff2) format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }


/* ======================================================================== */
/* THE SYSTEM. Tokens, the reset, the page ground, and the components that
   belong to no single section: the column, the kicker, the section head, the
   buttons, the closing band, the reveal. Nothing here knows what page it is on.
   The ladder, the ramp and the shadow vocabulary are specified in DESIGN.md. */
/* ======================================================================== */

  :root{
    color-scheme:dark;

    /* ground */
    --deep:#0f1c28; --mid:#1a2f42; --navy:#2a4a66; --ink:#0d1721;
    /* the one accent */
    --yellow:#fcbf03; --yellow-hi:#ffcf2e;
    /* text, quietest last */
    --white:#f5f7fa; --muted:#b0c4de; --meta:#9db2c8;
    /* lines and surfaces */
    --line:rgba(252,191,3,0.16);
    --hair:rgba(255,255,255,0.08);
    --card-border:rgba(252,191,3,0.28);
    --panel-bg:rgba(26,47,66,0.26);

    /* the accent at its four other documented strengths. nothing in between. */
    --y-wash:rgba(252,191,3,0.04);   /* a tint you read as texture, not colour */
    --y-tint:rgba(252,191,3,0.08);   /* a filled chip or an active cell */
    --y-edge:rgba(252,191,3,0.45);   /* an edge under the pointer */
    /* the same idea in white and in panel navy */
    --hair-lo:rgba(255,255,255,0.04);
    --hair-hi:rgba(255,255,255,0.16);
    --panel-2:rgba(26,47,66,0.5);
    /* the two surfaces that sit over the page */
    --chrome:rgba(15,28,40,0.9);     /* the fixed bars */
    --scrim:rgba(10,18,26,0.9);      /* behind a modal */
    /* lift */
    --shadow-lift:0 26px 64px rgba(0,0,0,0.42);
    --shadow-modal:0 30px 90px rgba(0,0,0,0.6);
    /* the accent lifts too. DESIGN.md's shadow vocabulary names every job a
       yellow shadow is allowed to do: a control answering the pointer, a live
       handle, the closing panel, and the home page's one loud tier. */
    --shadow-glow:0 10px 26px var(--line);
    --ring-glow:0 0 0 4px var(--line);
    /* the closing panel's halo. Spread over 40 and 60 pixels --y-wash reads
       correctly, so this shadow is on the ladder like every other colour. */
    --shadow-card:0 0 40px var(--y-wash), inset 0 0 60px var(--y-wash);
    /* the one colour that is not the accent, and why */
    --warn:255,120,110;              /* a field that will not validate */

    /* THE SURFACE. One card recipe for the whole site, chosen in _card_lab.html:
       a present translucent navy, a diagonal white sheen, a frosted blur, a one
       pixel light catch on the top edge, and a soft float. Every card, panel,
       band and modal reads its look from these five, so a tweak is one edit. */
    --surf:linear-gradient(157deg, rgba(255,255,255,0.08),
      rgba(255,255,255,0.014) 45%, rgba(26,47,66,0) 90%), rgba(26,47,66,0.10);
    --surf-line:rgba(252,191,3,0.30);
    --surf-blur:blur(16px) saturate(1.1);
    --surf-hl:inset 0 1px 0 rgba(255,255,255,0.10);
    --surf-shadow:0 20px 50px rgba(0,0,0,0.47);
    /* the same sheen over an opaque ground, for a surface that has to cover
       content rather than sit over it: a dialog, and the open nav menu. A
       translucent panel with text behind it is only legible while
       backdrop-filter is supported, which is not a thing to bet reading on. */
    --surf-solid:linear-gradient(157deg, rgba(255,255,255,0.08),
      rgba(255,255,255,0.014) 45%, rgba(26,47,66,0) 90%), var(--deep);

    /* THE ACCENTED SURFACE. Three panels on the home page take the accent into
       the glass in place of the white sheen, and the strength runs with how
       loudly the panel is asking to be looked at: the foundation strip, a door
       card under the pointer, and the one tier that gets to shout. They were
       written out longhand in the home page's own stylesheet, which made them
       the only colours on the site that were not token definitions and the
       only exception to the ladder. Same pixels, named once. */
    --surf-y1:linear-gradient(157deg, rgba(252,191,3,0.06),
      rgba(255,255,255,0.012) 45%, rgba(26,47,66,0) 90%), rgba(26,47,66,0.10);
    --surf-y2:linear-gradient(157deg, rgba(252,191,3,0.09),
      rgba(255,255,255,0.01) 45%, rgba(26,47,66,0) 90%), var(--panel-2);
    --surf-y3:linear-gradient(157deg, rgba(252,191,3,0.14),
      rgba(252,191,3,0.03) 45%, rgba(26,47,66,0) 92%), rgba(26,47,66,0.10);
    --surf-y-glow:0 0 60px rgba(252,191,3,0.15);
    --surf-hl-hi:inset 0 1px 0 rgba(255,255,255,0.14);
    --shadow-hover:0 30px 70px rgba(0,0,0,0.5);

    /* corners */
    --r-card:8px; --r-ui:4px;

    /* the spacing scale. every gap on this site comes from this list. */
    --s1:4px;  --s2:8px;   --s3:12px;  --s4:16px;
    --s5:20px; --s6:24px;  --s7:32px;  --s8:40px;
    --s9:48px; --s10:64px; --s11:80px; --s12:96px;
    --sec:80px;        /* rhythm between blocks inside a section */
    --gutter:40px;     /* the column's side padding */
    --col:1080px;      /* the column itself, identical in every section */

    /* the type ramp. every font-size on this site comes from this list. */
    --fs-label:11px;    /* the smallest type on the site. nav, badges, labels */
    /* The section opener rides its own step. It sat on the 11px floor while the
       type it introduces is a clamp, so on a wide screen it was a seventh of
       the hero and on a phone a third of it: that is not one relationship, it
       is two, and only the phone one was ever designed. It scales with the
       headline now and stops at 15, still under body copy, because a label that
       outweighs the sentence it introduces is a label doing the headline's job.
       The floor stays 11 so nothing changes on a phone, where the line is
       already as wide as the screen allows. */
    --fs-kicker:clamp(11px,1.4vw,15px);
    --kicker-rule:clamp(30px,4vw,48px);  /* the rule beside a kicker, scaled with it */
    --fs-small:13px;    /* buttons, meta, small print */
    --fs-dense:14px;    /* tables and dense lists */
    --fs-body:15.5px;   /* body copy */
    --fs-lead:clamp(15px,1.2vw,17px);   /* the sentence under a title */
    --fs-h5:18px;
    --fs-h4:clamp(21px,2vw,26px);
    --fs-h3:clamp(22px,2.5vw,30px);
    --fs-h2:clamp(30px,3.5vw,46px);
    --fs-hero:clamp(40px,5.4vw,78px);
    --fs-big:clamp(52px,7.5vw,96px);    /* a headline number inside a card */
    --fs-mega:clamp(58px,9vw,124px);    /* a headline number at full width */


    /* tracking. five decisions, not eighteen. */
    --tr-tight:-0.02em;  /* a headline set in Anton or DM Sans 700 */
    --tr-read:0.04em;    /* type you read: a mono numeral, an address, a button */
    --tr-ui:0.1em;       /* a nav link, and the small uppercase controls */
    --tr-label:0.16em;   /* a small uppercase mono label */
    --tr-kicker:0.28em;  /* the section opener */
    /* motion */
    --ease:cubic-bezier(.22,.61,.36,1);
    --t-state:.25s; --t-surface:.3s; --t-arrival:.6s;
  }

  *{ margin:0; padding:0; box-sizing:border-box; }

  /* `hidden` must win, and this is the one !important on the site.
     It earns it. 28 September 2026, on the live site: pressing Got it on the
     cookie card did nothing at all. The click fired, the choice was written to
     storage, and the card stayed on screen, on every device, for good.
     The cause was not in the javascript. The script sets bar.hidden = true,
     which relies on the browser's own [hidden]{display:none}. But .cookie
     sets display:flex in THIS stylesheet, and an author rule beats a browser
     rule whatever the specificity, so the card kept its display and the
     attribute did nothing. Equal specificity hid it: both selectors are one
     class worth, so nothing looked wrong in either file.
     Declared here rather than on .cookie because the bug belongs to the
     mechanism and not to that one card: the next element hidden this way, in
     a year, by somebody who has never read this comment, must not have to
     rediscover it. `hidden` means the element is not there. A layout rule may
     not outvote that. */
  [hidden]{ display:none !important; }

  @media (prefers-reduced-motion:no-preference){ html{ scroll-behavior:smooth; } }
  body{ background:var(--deep); color:var(--white); font-family:'DM Sans',sans-serif;
    -webkit-font-smoothing:antialiased; overflow-x:hidden; }

  /* the sheet the whole site is drawn on: one faint measuring grid and
     one soft glow, identical everywhere so the sections compose. */
  .bg{ position:fixed; inset:0; z-index:0; pointer-events:none;
    background-image:linear-gradient(var(--y-wash) 1px,transparent 1px),
      linear-gradient(90deg,var(--y-wash) 1px,transparent 1px);
    background-size:64px 64px;
    -webkit-mask-image:radial-gradient(ellipse 90% 70% at 50% 30%,#000 40%,transparent 100%);
    mask-image:radial-gradient(ellipse 90% 70% at 50% 30%,#000 40%,transparent 100%); }
  .glow{ position:fixed; top:-10%; left:50%; transform:translateX(-50%);
    width:70vw; height:60vh; z-index:0; pointer-events:none; filter:blur(20px);
    background:radial-gradient(circle,var(--y-tint),transparent 62%); }

  ::selection{ background:var(--yellow); color:var(--ink); }
  ::-moz-selection{ background:var(--yellow); color:var(--ink); }

  /* one focus ring, on every focusable thing, in every section, keyboard only */
  a:focus-visible, button:focus-visible, summary:focus-visible,
  input:focus-visible, textarea:focus-visible, select:focus-visible,
  [tabindex]:focus-visible{ outline:2px solid var(--yellow); outline-offset:3px; }

  .wrap{ position:relative; z-index:1; max-width:var(--col); margin:0 auto;
    padding:var(--s12) var(--gutter); }

  .kicker{ font-family:'DM Mono',monospace; font-weight:500; font-size:var(--fs-kicker);
    letter-spacing:var(--tr-kicker); text-transform:uppercase; color:var(--yellow);
    display:inline-flex; align-items:center; flex-wrap:wrap; gap:var(--s2) var(--s3);
    margin-bottom:var(--s6); }
  /* The rule sits to the left of an aligned kicker. The closing band is the
     only centred one and declares its own second rule, in its own block, so
     this no longer names a class that lives on one page. */
  .kicker::before{ content:''; width:var(--kicker-rule); height:1px;
    background:var(--yellow); opacity:.6; }

  .head{ margin-bottom:var(--s10); }
  .sec-title{ font-family:'Anton',sans-serif; font-weight:400; font-size:var(--fs-h2);
    line-height:1.06; letter-spacing:0; max-width:30ch; }
  .sec-title .l2{ color:var(--muted); }
  /* 32em, not 560px. Measured on the real paragraph: a 560px box holds 67
     characters a line at 17px, 75 at 15.5 and 80 at 15, against a band of
     58 to 70, because the box was fixed and the font is a clamp. The 58ch
     half never bit: 58ch is wider than 560px at every size on the ladder.
     32em is the same cap in the font own unit, 544px at 17 and 480 at 15,
     and it measures 65 characters at both. text-wrap:pretty is here
     because five page sources carry it and this file did not, and this
     file is the one the build emits, so it was shipping on no page. */
  .sec-intro{ color:var(--muted); font-size:var(--fs-lead); line-height:1.65;
    max-width:32em; margin-top:var(--s5); text-wrap:pretty; }
  .sec-intro b{ color:var(--white); font-weight:500; }

  /* a row that holds a button pair, wherever a section puts one */
  .cta-row{ display:flex; flex-wrap:wrap; align-items:center; gap:var(--s5) var(--s6); margin-top:var(--s7); }

  .btn, .btn-ghost, .btn-text{ -webkit-appearance:none; appearance:none;
    font-family:'DM Sans',sans-serif; font-size:var(--fs-small); font-weight:700; letter-spacing:var(--tr-read);
    text-transform:uppercase; text-decoration:none; cursor:pointer; white-space:nowrap;
    display:inline-flex; align-items:center; justify-content:center; gap:var(--s3); }
  .btn .ar, .btn-ghost .ar, .btn-text .ar{ font-size:var(--fs-small); line-height:1; }

  .btn{ padding:var(--s4) var(--s6); border:1px solid var(--yellow); border-radius:var(--r-ui);
    background:var(--yellow); color:var(--ink);
    transition:transform var(--t-state) var(--ease), box-shadow var(--t-state) var(--ease), background var(--t-state) var(--ease); }
  .btn:hover{ background:var(--yellow-hi); transform:translateY(-2px); box-shadow:var(--shadow-glow); }
  .btn:active{ transform:translateY(0); box-shadow:none; }
  .btn:focus-visible{ outline:2px solid var(--white); outline-offset:3px; }

  .btn-ghost{ padding:var(--s4) var(--s6); border:1px solid var(--line); border-radius:var(--r-ui);
    background:transparent; color:var(--muted);
    transition:transform var(--t-state) var(--ease), color var(--t-state) var(--ease), border-color var(--t-state) var(--ease); }
  .btn-ghost:hover{ color:var(--yellow); border-color:var(--y-edge); transform:translateY(-2px); }
  .btn-ghost:active{ transform:translateY(0); }
  .btn-ghost:focus-visible{ outline:2px solid var(--white); outline-offset:3px; }

  .btn-text{ background:transparent; border:none; color:var(--white); padding:var(--s1) 0;
    border-bottom:1px solid var(--card-border); position:relative;
    transition:color var(--t-state) var(--ease), border-color var(--t-state) var(--ease); }
  .btn-text:hover{ color:var(--yellow); border-bottom-color:var(--yellow); }
  .btn-text:focus-visible{ outline:2px solid var(--yellow); outline-offset:4px; }
  /* 193 by 26, where a finger asks for 44. There is nowhere to put padding:
     the underline is this element own border-bottom, so padding would
     push the line away from the word it belongs to. So the target grows
     and the layout does not. Out of flow, 44 tall, centred on the text,
     and nothing on the page moves by a pixel. The nav link draws its
     yellow rule the same way. */
  .btn-text::before{ content:''; position:absolute; left:0; right:0; top:50%;
    transform:translateY(-50%); height:44px; }
  .btn-text .ar{ color:var(--yellow); }
  /* webmail users cannot use a mailto link, so hand them the address itself */
  .btn-ghost svg{ width:13px; height:13px; flex:none; }
  .btn-ghost.done{ color:var(--yellow); border-color:var(--y-edge); }
  .sr{ position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; }

  .cta{ margin-top:var(--sec); position:relative; overflow:hidden;
    border:1px solid var(--surf-line); border-radius:var(--r-card);
    background:var(--surf); -webkit-backdrop-filter:var(--surf-blur);
    backdrop-filter:var(--surf-blur);
    box-shadow:var(--surf-hl), var(--shadow-card), var(--surf-shadow); }
  .cta::before{ content:''; position:absolute; inset:0; pointer-events:none;
    background:radial-gradient(ellipse 60% 120% at 50% 0%,var(--y-tint),transparent 70%); }
  .cta-inner{ position:relative; padding:var(--s9) var(--s7); text-align:center; }
  .cta .kicker{ justify-content:center; margin-bottom:var(--s6); }
  .cta .kicker::after{ content:''; width:var(--kicker-rule); height:1px;
    background:var(--yellow); opacity:.6; }
  .cta h2{ font-family:'Anton',sans-serif; font-weight:400; font-size:var(--fs-h2);
    line-height:1.08; letter-spacing:0; color:var(--white); text-wrap:balance;
    max-width:22ch; margin:0 auto; }
  .cta-sub{ margin:var(--s4) auto 0; font-size:var(--fs-body); color:var(--muted); line-height:1.7; max-width:32em; }
  .cta .cta-row{ justify-content:center; margin-top:var(--s6); }
  .cta-meta{ margin-top:var(--s7); padding-top:var(--s6); border-top:1px solid var(--hair);
    display:flex; flex-wrap:wrap; justify-content:center; gap:var(--s2) var(--s3);
    font-family:'DM Mono',monospace; font-weight:500; font-size:var(--fs-label); letter-spacing:var(--tr-ui);
    text-transform:uppercase; color:var(--muted); }
  .cta-meta span{ display:inline-flex; align-items:center; gap:var(--s2); line-height:1;
    padding:var(--s2) var(--s4); border-radius:var(--r-ui);
    background:var(--hair-lo); border:1px solid var(--line); }
  .cta-meta span::before{ content:''; width:5px; height:5px; border-radius:50%;
    background:var(--yellow); flex:0 0 auto; }

  .js .rv{ opacity:0; transform:translateY(18px);
    transition:opacity var(--t-arrival) var(--ease), transform var(--t-arrival) var(--ease); }
  .js .rv.in{ opacity:1; transform:none; }
  @media (prefers-reduced-motion:reduce){ .js .rv{ opacity:1; transform:none; transition:none; } }

  /* One section carried this and five did not, so the same request produced
     five different sites. It belongs to everything or to nothing. */
  @media (prefers-reduced-motion:reduce){
    *, *::before, *::after{ transition-duration:.01ms !important;
      animation-duration:.01ms !important; }
  }

  @media (prefers-reduced-motion:no-preference){
    .modal.open .modal-box{ animation:pop .3s var(--ease); }
    @keyframes pop{ from{ opacity:0; transform:translateY(14px); } to{ opacity:1; transform:none; } }
  }


/* ======================================================================== */
/* THE CHROME. What wraps every page: the fixed bar, the navigation, the pager,
   the footer, the cookie card and the two modals. This file is the only copy.
   pages/07_contact_footer/BRIEF.md is the brief it answers to. */
/* ======================================================================== */

  /* A topic page opens under the fixed bar, so its first block carries the
     bar's height on top of its own padding. The home page does not use this:
     its hero pads itself, because the horizon has to run under the bar. */
  .wrap.page-top{ padding-top:calc(var(--hdr) + var(--s10)); }

  /* Five nav links and a header on every page is exactly the case the skip
     link exists for. Off screen until it is focused, then the first thing. */
  .skip{ position:absolute; left:var(--s4); top:-100px; z-index:1100;
    font-family:'DM Mono',monospace; font-weight:500; font-size:var(--fs-small);
    letter-spacing:var(--tr-ui); text-transform:uppercase; text-decoration:none;
    color:var(--ink); background:var(--yellow); padding:var(--s3) var(--s5);
    border-radius:var(--r-ui); transition:top var(--t-state) var(--ease);
    display:inline-flex; align-items:center; min-height:44px; }
  .skip:focus{ top:var(--s4); }

  /* ══ fixed chrome ══ */
  /* Two numbers, and they are not the same number. --hdr is the clearance a
     page reserves under the bar: the home page redeclares it at 104 because
     its horizon runs behind the bar and the hero pads itself clear of that.
     --bar is the bar. It was missing, so the bar had no height of its own and
     took whatever its tallest child was: 61px with a 60px logo in it, and 70
     between the breakpoint and 1170 where the labels wrap before anything
     else gives. Stated, the bar cannot be grown by its own contents. */
  :root{ --hdr:64px; --bar:64px; }
  .header-fixed{ position:fixed; top:0; left:0; right:0; z-index:1000; }
  .header-fixed nav{ height:var(--bar); padding:0 var(--gutter);
    display:flex; justify-content:space-between; align-items:center;
    gap:var(--s6); background:var(--chrome);
    -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
    border-bottom:1px solid var(--surf-line); }
  /* 44 inside 64 is ten pixels of air over the mark and ten under it. At 60 it
     had none: the bar was as tall as the logo and the logo touched both
     hairlines. 44 is the size the footer mark already takes on a phone. */
  .logo-wrap svg{ height:44px; width:auto; display:block; }
  .nav-links{ display:flex; gap:var(--s6); }
  /* Annotation Blue at rest, one rung above the Dimension Grey the ladder
     gives a label, by founder decision of 12 September: 9.7:1 against the page
     ground where the grey was 7.9. One rung and not two, because Paper White
     would leave hover nowhere to go and would put six labels level with the
     logo and the button. Hover still travels 9.7 to 16.1. */
  .nav-links a{ font-family:'DM Mono',monospace; font-size:var(--fs-label);
    letter-spacing:var(--tr-ui); text-transform:uppercase; color:var(--muted);
    text-decoration:none; position:relative; padding:var(--s5) var(--s2);
    transition:color var(--t-state) var(--ease); }
  .nav-links a::after{ content:''; position:absolute; left:var(--s2); right:var(--s2);
    bottom:var(--s4);
    height:1px; background:var(--yellow);
    transform:scaleX(0); transform-origin:left;
    transition:transform var(--t-state) var(--ease); }
  .nav-links a:hover{ color:var(--white); }
  .nav-links a:hover::after{ transform:scaleX(1); }
  /* The right side holds two controls, not a link and a button. --s3 closes
     them into one cluster; at --s5 the LinkedIn link sat 20px from the button
     and 148px from the last nav label, so it belonged to the button by
     distance and to the nav by appearance, and the bar read as seven links. */
  .nav-right{ display:flex; align-items:center; gap:var(--s3); }
  /* LinkedIn keeps its mark and loses its word, at every width. The word was
     the defect: it gave the link the face, the size, the tracking, the case
     and the colour of a nav link, so it read as one. A 14px glyph is not a
     target, so the mark is padded out to 44 square and takes the menu
     button's border, --line, the only outlined 44 this bar has ever had. */
  .nav-li{ display:inline-flex; align-items:center; justify-content:center;
    flex:0 0 44px; width:44px; height:44px; padding:0;
    border:1px solid var(--line); border-radius:var(--r-ui);
    color:var(--muted); text-decoration:none;
    transition:color var(--t-state) var(--ease),
      border-color var(--t-state) var(--ease); }
  /* The label is not shown, but it must still be READ. display:none takes the
     text out of the accessibility tree as well as out of the layout, and then
     the only content left in the link is an aria-hidden svg, so the link has
     no name at all: a screen reader announces "link" and stops. Lighthouse
     called this on 28 September, "Links do not have a discernible name", and
     it was right. Clipped to a pixel instead, which hides it from the eye and
     keeps it for the reader. Same recipe as .sr. */
  .nav-li span{ position:absolute; width:1px; height:1px; overflow:hidden;
    clip:rect(0 0 0 0); white-space:nowrap; }
  .nav-li:hover{ color:var(--yellow); border-color:var(--y-edge); }
  .nav-li svg{ width:17px; height:17px; fill:currentColor; }

  /* The toggle is absent above the breakpoint and a real control below it. Its
     base rule was written into the compose script and never came here, so for
     one build it rendered as three bare spans sitting in the nav. */
  .header-fixed nav{ position:relative; }
  .nav-toggle{ display:none; flex:0 0 44px; width:44px; height:44px; padding:0;
    background:none; border:1px solid var(--line); border-radius:var(--r-ui);
    cursor:pointer; flex-direction:column; align-items:center; justify-content:center;
    gap:5px; transition:border-color var(--t-state) var(--ease); }
  .nav-toggle span{ display:block; width:18px; height:1px; background:var(--muted);
    transition:transform var(--t-surface) var(--ease), opacity var(--t-state) var(--ease),
      background var(--t-state) var(--ease); }
  .nav-toggle:hover{ border-color:var(--y-edge); }
  .nav-toggle:hover span{ background:var(--yellow); }
  .nav-toggle[aria-expanded="true"] span:nth-child(1){ transform:translateY(6px) rotate(45deg); }
  .nav-toggle[aria-expanded="true"] span:nth-child(2){ opacity:0; }
  .nav-toggle[aria-expanded="true"] span:nth-child(3){ transform:translateY(-6px) rotate(-45deg); }

  /* The page you are on keeps the underline the others only borrow on hover,
     and it takes the accent, which is what the accent is for: DESIGN.md's One
     Accent Rule gives yellow to the current state, the primary action and the
     one accented panel, and nothing else. It was white here and yellow on a
     phone, so the two disagreed and the desktop was the one that was wrong.
     A hue is also a louder signal than a step in lightness, which is the
     whole point of marking where you are. */
  .nav-links a.here{ color:var(--yellow); }
  .nav-links a.here::after{ transform:scaleX(1); }


  /* ══ the pager ══ */
  /* Six documents cannot be scrolled through, so the sequence has to be stated.
     This is the quiet end of the page: mono, hairlines, no fill. The loud close
     is the band above it, and two loud things at the end of a page is none. */
  /* no margin of its own: the block above already ends on the column's
     bottom padding, and adding to it opened a hole between the two */
  .pager{ position:relative; z-index:1; border-top:1px solid var(--line); }
  .pager-in{ max-width:var(--col); margin:0 auto;
    display:grid; grid-template-columns:1fr 1fr; }
  .pg{ display:flex; flex-direction:column; gap:var(--s3); text-decoration:none;
    padding:var(--s7) var(--gutter);
    transition:background var(--t-state) var(--ease); }
  .pg + .pg{ border-left:1px solid var(--hair); }
  .pg-l{ display:inline-flex; align-items:center; gap:var(--s2);
    font-family:'DM Mono',monospace; font-weight:500; font-size:var(--fs-label);
    letter-spacing:var(--tr-label); text-transform:uppercase; color:var(--meta); }
  .pg-t{ font-family:'DM Sans',sans-serif; font-weight:700; font-size:var(--fs-h5);
    letter-spacing:var(--tr-tight); color:var(--white);
    transition:color var(--t-state) var(--ease); }
  .pg.next{ align-items:flex-end; text-align:right; }
  .pg:hover{ background:var(--y-wash); }
  .pg:hover .pg-t{ color:var(--yellow); }
  .pg .ar{ transition:transform var(--t-state) var(--ease); }
  .pg.prev:hover .ar{ transform:translateX(-3px); }
  .pg.next:hover .ar{ transform:translateX(3px); }
  .pg:focus-visible{ outline:2px solid var(--yellow); outline-offset:-3px; }

  /* ══ footer ══ */
  /* Shared chrome, and pages/07_contact_footer/BRIEF.md is the file that owns
     it. Every page of a multi page site ends here, so it carries the identity,
     the four ways to make contact, and the legal line. */
  .foot{ position:relative; z-index:1; border-top:1px solid var(--line);
    background:var(--panel-bg); }
  .foot-in{ max-width:var(--col); margin:0 auto; padding:var(--s10) var(--gutter) var(--s8);
    display:grid; grid-template-columns:minmax(0,1fr) auto; gap:var(--s7) var(--s10);
    align-items:start; }
  .foot-mark{ display:block; }
  .foot-mark svg{ height:52px; width:auto; display:block; }
  .foot-mark:focus-visible{ outline:2px solid var(--yellow); outline-offset:4px; }
  .foot-say{ margin-top:var(--s4); font-size:var(--fs-dense); color:var(--muted);
    line-height:1.7; max-width:48ch; text-wrap:pretty; }
  .foot-links{ display:flex; flex-direction:column; align-items:flex-end; gap:var(--s3); }
  .foot-links a, .foot-links button{ font-family:'DM Mono',monospace; font-weight:500;
    font-size:var(--fs-small); letter-spacing:var(--tr-ui); text-transform:uppercase;
    color:var(--meta); background:none; border:0; padding:var(--s2) 0; cursor:pointer;
    text-decoration:none; transition:color var(--t-state) var(--ease);
    /* 13px mono in 8px of padding came to 33.5, under the 44 the cookie
       dismiss was already fixed to. The row is the target, not the glyphs. */
    display:inline-flex; align-items:center; min-height:44px; }
  .foot-links a:hover, .foot-links button:hover{ color:var(--yellow); }
  .foot-legal{ max-width:var(--col); margin:0 auto;
    padding:var(--s5) var(--gutter) var(--s8); border-top:1px solid var(--hair-lo);
    display:flex; flex-wrap:wrap; justify-content:space-between; gap:var(--s2) var(--s5);
    font-family:'DM Mono',monospace; font-size:var(--fs-small); color:var(--meta); }

  /* ══ cookie bar ══ */
  .cookie{ position:fixed; right:var(--gutter); bottom:var(--s5); z-index:900;
    max-width:390px; display:flex; flex-wrap:wrap; align-items:center;
    gap:var(--s3) var(--s4); padding:var(--s4) var(--s5);
    background:var(--chrome); -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px);
    border:1px solid var(--line); border-radius:var(--r-card); box-shadow:var(--shadow-lift);
    font-family:'DM Sans',sans-serif; font-size:var(--fs-small); line-height:1.6;
    color:var(--meta); }
  .cookie span{ flex:1 1 200px; }
  /* A button, as the footer own privacy control already is. It was an
     anchor to "#", which claims a navigation it does not have. The plain
     click was already preventDefault, so the only symptoms were the ones
     a link offers besides clicking: a middle click opened a new tab at
     the top of the same page with no modal on it, and copy link address
     handed over an address that means nothing. These declarations are
     what the anchor was giving for free. */
  .cookie .pp{ -webkit-appearance:none; appearance:none; background:none;
    border:none; padding:0; font:inherit; color:var(--yellow);
    text-decoration:underline; cursor:pointer; position:relative; }
  /* 20.8 drawn, where a finger asks for 44. Padding cannot do it: this
     is a word inside a running sentence and padding would push the
     sentence apart. So the same device .btn-text uses, out of flow, 44
     tall, centred on the text, and nothing in the card moves. The band
     is held to the word and not run to the edges of the line box,
     because this word ends a wrapped line and a full width band would
     put a 44px target over the sentence above it. */
  .cookie .pp::before{ content:''; position:absolute; left:0; right:0;
    top:50%; transform:translateY(-50%); height:44px; }
  .cookie .pp:hover{ color:var(--yellow-hi); }
  .cookie .pp:focus-visible{ outline:2px solid var(--yellow); outline-offset:2px; }
  .cookie-btns{ display:flex; align-items:center; gap:var(--s3); }
  .cookie-ok{ font-family:'DM Mono',monospace; font-weight:500; font-size:var(--fs-label);
    letter-spacing:var(--tr-ui); text-transform:uppercase; cursor:pointer;
    background:var(--yellow); color:var(--ink); border:none; border-radius:var(--r-ui);
    padding:var(--s3) var(--s5); min-height:44px; }
  /* 44px, because a dismiss is a target and 34 was the only control on the
     site failing both axes of it */
  .cookie-x{ width:44px; height:44px; display:flex; align-items:center; justify-content:center;
    background:none; border:1px solid var(--line); border-radius:var(--r-ui);
    color:var(--meta); cursor:pointer; font-size:var(--fs-small);
    transition:color var(--t-state) var(--ease), border-color var(--t-state) var(--ease); }
  .cookie-x:hover{ color:var(--yellow); border-color:var(--y-edge); }
  /* The class was written onto <body> in every page and there was never a rule
     for it, so the card sat on top of whatever was at the bottom of the page:
     a door card on the home page, the contact and LinkedIn links in the
     footer. While the card is up the page carries its height, and the moment
     it is dismissed the space goes back. */
  body.cookie-up{ padding-bottom:calc(var(--s12) + var(--s6)); }
  /* two things over the page at once, one of them asking for a decision. The
     card waits until the dialog is done. */
  body.locked .cookie{ display:none; }

  /* ══ contact modal ══ */
  /* above the fixed bar (1000) and the cookie card (900). At 80 the header sat
     lit and clickable over an open dialog, so a click on a nav link threw away
     a half written message with no warning. A dialog is the top layer or it is
     not a dialog. */
  .modal{ position:fixed; inset:0; z-index:1200; display:none;
    align-items:center; justify-content:center; padding:var(--s6) var(--s5); }
  /* A phone's fixed overlay is as tall as the page WITHOUT the browser's own
     bars, because that is what the layout viewport is. The sheet below is
     bottom aligned inside it, so its bottom edge sat under the address bar and
     everything was pushed down by however tall that bar happened to be, which
     is how the only way out of a full screen notice ends up off screen.
     100dvh is the height you can actually see, it changes as the bar comes and
     goes, and on a desktop it is the same number as before. bottom:auto so the
     height is the one that decides, not inset. */
  @supports (height:100dvh){ .modal{ bottom:auto; height:100dvh; } }
  .modal.open{ display:flex; }
  .modal-back{ position:absolute; inset:0; background:var(--scrim);
    -webkit-backdrop-filter:blur(4px); backdrop-filter:blur(4px); }
  /* the modal keeps an opaque base so the form stays readable, but takes the
     same white sheen, top highlight, border and radius as every other surface */
  /* a column, so the head and the action row hold their place and only the
     fields scroll. It used to scroll as one block, which put Send under the
     fold inside the dialog on a laptop at 681px. */
  .modal-box{ position:relative; z-index:1; width:100%; max-width:560px;
    max-height:88vh; max-height:88dvh; display:flex; flex-direction:column; overflow:hidden;
    background:var(--surf-solid);
    border:1px solid var(--surf-line); border-radius:var(--r-card);
    box-shadow:var(--surf-hl), var(--shadow-modal); }
  .modal-head{ flex:none; padding:var(--s7) var(--s7) var(--s6);
    border-bottom:1px solid var(--hair); position:relative; }
  .modal-head .k{ font-family:'DM Mono',monospace; font-weight:500; font-size:var(--fs-label);
    letter-spacing:var(--tr-kicker); text-transform:uppercase; color:var(--yellow); margin-bottom:var(--s3); }
  .modal-head h2, .mdone h3{ font-family:'DM Sans',sans-serif; font-weight:700;
    line-height:1.2; letter-spacing:var(--tr-tight); color:var(--white); }
  .modal-head h2{ font-size:var(--fs-h4); max-width:18ch; }
  .modal-head p{ margin-top:var(--s3); font-size:var(--fs-dense); color:var(--muted);
    line-height:1.65; max-width:44ch; }
  /* THE LIGHTBOX. Same dialog machinery as the form modal, opposite shape.
     .modal-box is 560 because a form should not be wider than a readable
     measure; a screenshot of a desktop application wants every pixel the
     viewport will give it, so this one takes the viewport and lets the image
     sit at its natural size up to that. object-fit:contain means a wide
     drawing sheet and a 16:9 screen both land whole, without either being
     cropped or stretched.

     No surface, no border, no sheen. The glass recipe is for panels that sit
     over the page; here the picture IS the content and a frame around it is
     just something between the reader and the thing he tapped to see. */
  .modal.lightbox{ padding:var(--s5); }
  /* overflow:visible, and it is load bearing. The base .modal-box clips its
     own overflow, which is right for a form whose fields scroll inside it.
     The close control on THIS dialog is deliberately outside the picture,
     placed at a negative top, so the clip painted it out of existence: on a
     phone the cross was in the layout, 44 by 44, on screen, and invisible,
     and a tap where it should be landed on the backdrop behind it. Checked on
     28 September at 412 by 823 and 390 by 660: the topmost element at the
     centre of the cross was .modal-back. The dialog still closed, because the
     backdrop closes it too, but a reader who cannot see a way out does not
     tap hopefully, he reloads the page. */
  .lightbox .modal-box{ max-width:min(1600px, 96vw); max-height:92vh;
    width:auto; background:none; border:none; box-shadow:none;
    overflow:visible;
    align-items:center; justify-content:center; }
  /* touch-action:none is required, not tidy. Without it the browser takes
     the pinch for its own page zoom and the script never sees the second
     pointer, so the viewer silently does nothing on the one device it was
     written for. max-height is 92vh and the scale is a transform, so zooming
     never reflows anything: the picture is painted larger inside a box whose
     layout size does not move. */
  .lightbox img{ display:block; max-width:100%; max-height:92vh;
    width:auto; height:auto; object-fit:contain;
    touch-action:none; will-change:transform;
    border-radius:var(--r-ui); box-shadow:var(--shadow-modal); }
  .lightbox .zoom-hint{ flex:none; margin:var(--s3) 0 0;
    font-family:'DM Mono',monospace; font-weight:500;
    font-size:var(--fs-label); letter-spacing:var(--tr-ui);
    color:var(--muted); text-align:center; pointer-events:none; }
  /* the close control moves outside the picture, because 17px inside the top
     right corner of a screenshot is on top of the screenshot */
  /* z-index, and it is load bearing for the same reason overflow:visible is.
     will-change:transform on the picture gives it its own stacking context,
     which lifted it above the close control: at 1280 by 800 the topmost
     element at the centre of the cross became the IMG. The dialog still
     closed, because a click on the picture closes it too, which is exactly
     the kind of accident that hides a broken control. */
  .lightbox .modal-x{ top:calc(var(--s5) * -1); right:0; z-index:2;
    background:var(--chrome); }
  @media(max-width:600px){
    .modal.lightbox{ padding:var(--s9) var(--s4) var(--s4); }
    .lightbox .modal-x{ top:calc(var(--s9) * -1 + var(--s1)); }
  }

  /* The privacy dialog is now a document rather than four sentences, so it
     gets the one thing a document needs and the form did not: subheads, and a
     body that scrolls on its own while the head and the close control hold
     their place. --fs-h5 rather than a heading rung, because these are
     signposts inside a dialog and not titles on a page. */
  #privacyModal .modal-body h3{ font-family:'DM Sans',sans-serif; font-weight:700;
    font-size:var(--fs-h5); line-height:1.3; letter-spacing:var(--tr-tight);
    color:var(--white); margin:var(--s6) 0 var(--s2); }
  #privacyModal .modal-body h3:first-child{ margin-top:0; }
  #privacyModal .modal-body p{ margin:0 0 var(--s3); }
  #privacyModal .modal-body p:last-child{ margin-bottom:0; }

  .modal-x{ position:absolute; top:17px; right:17px; width:44px; height:44px;
    display:flex; align-items:center; justify-content:center; cursor:pointer;
    background:transparent; border:1px solid var(--hair); border-radius:var(--r-ui);
    color:var(--muted); font-size:var(--fs-body); line-height:1;
    transition:color var(--t-state) var(--ease), border-color var(--t-state) var(--ease); }
  .modal-x:hover{ color:var(--yellow); border-color:var(--line); }
  .modal-x:focus-visible{ outline:2px solid var(--yellow); outline-offset:3px; }

  .mform{ display:flex; flex-direction:column; min-height:0; }
  .mfields{ overflow-y:auto; padding:var(--s6) var(--s7) var(--s2); }
  .mfoot{ flex:none; padding:var(--s5) var(--s7) var(--s7);
    border-top:1px solid var(--hair); background:var(--deep); }
  .mrow{ margin-bottom:var(--s5); }
  .mrow label{ display:block; font-family:'DM Mono',monospace; font-weight:500; font-size:var(--fs-label);
    letter-spacing:var(--tr-label); text-transform:uppercase; color:var(--meta); margin-bottom:var(--s2); }
  .mrow label .opt{ color:var(--meta); opacity:.65; letter-spacing:var(--tr-ui); }
  .mrow input, .mrow textarea{ width:100%; background:var(--panel-bg);
    border:1px solid var(--hair); border-radius:var(--r-ui); padding:var(--s3) var(--s3);
    font-family:'DM Sans',sans-serif; font-size:var(--fs-body); color:var(--white); line-height:1.5;
    transition:border-color var(--t-state) var(--ease), background var(--t-state) var(--ease); }
  .mrow textarea{ min-height:104px; resize:vertical; }
  .mrow input::placeholder, .mrow textarea::placeholder{ color:var(--meta); opacity:.55; }
  /* the border lift is the pointer answer; the ring is the keyboard answer.
     Switching the outline off for both was how the least visible focus state
     on the site ended up inside the one dialog that matters. */
  .mrow input:focus, .mrow textarea:focus{ border-color:var(--yellow);
    background:var(--panel-2); }
  .mrow input:focus:not(:focus-visible),
  .mrow textarea:focus:not(:focus-visible){ outline:none; }
  .mrow input:focus-visible, .mrow textarea:focus-visible{
    outline:2px solid var(--yellow); outline-offset:3px; }
  .mrow input:invalid:not(:placeholder-shown){ border-color:rgba(var(--warn),0.5); }
  /* a field that failed keeps the warn edge even while it has focus, so it
     never wears yellow, which on this site means the thing that is going right */
  .mrow input.bad, .mrow input.bad:focus{ border-color:rgba(var(--warn),0.6);
    background:rgba(var(--warn),0.06); }
  .mrow input.bad:focus-visible{ outline-color:rgb(var(--warn)); }
  .hp{ position:absolute; left:-9999px; opacity:0; height:0; width:0; }
  .mform .btn{ width:100%; margin-top:var(--s1); }
  .mnote{ margin-top:var(--s4); font-family:'DM Sans',sans-serif; font-size:var(--fs-small);
    color:var(--meta); line-height:1.7; }
  /* the message sits above the button now. Below it, a visitor who had just
     pressed the button was being answered underneath their own thumb. */
  .mstate{ display:none; font-size:var(--fs-dense); line-height:1.7; padding:var(--s4) var(--s4);
    margin-bottom:var(--s4);
    border:1px solid var(--line); border-radius:var(--r-ui);
    background:var(--y-wash); color:var(--muted); }
  .mstate b{ color:var(--white); font-weight:500; }
  .mstate.show{ display:block; }
  .mstate.err{ border-color:rgba(var(--warn),0.35); background:rgba(var(--warn),0.06); }
  .mdone{ display:none; min-height:0; overflow-y:auto;
    padding:var(--s8) var(--s7) var(--s9); text-align:center; }
  .mdone .tick{ width:52px; height:52px; margin:0 auto var(--s5); border-radius:50%;
    border:1px solid var(--line); background:var(--y-wash);
    display:flex; align-items:center; justify-content:center; color:var(--yellow); font-size:var(--fs-h4); }
  .mdone h3{ font-size:var(--fs-h4); }
  .mdone p{ margin:var(--s3) auto 0; font-size:var(--fs-body); color:var(--muted); line-height:1.7; max-width:38ch; }
  .modal.sent .mform{ display:none; }
  .modal.sent .mdone{ display:block; }
  /* pinned, not just clipped. The script writes the negative top offset, so the
     page holds its place under the dialog and closing it puts you back on the
     line you were reading instead of the top of the page. */
  body.locked{ position:fixed; top:0; left:0; right:0; width:100%; overflow:hidden; }

  /* ══ privacy modal, the same box as the contact one ══ */
  /* the box is a column now, so anything that can outgrow it scrolls itself */
  .modal-body{ min-height:0; overflow-y:auto; padding:var(--s6) var(--s7) var(--s7); }
  /* The notice used to offer one exit, the 44px cross at the top, and on a
     phone that is a screenful of legal text away from your thumb and above the
     scroll. The contact form has always had a real action row at the bottom.
     This gives the notice the same one. Escape and the backdrop still work;
     neither is available to somebody reading on a phone. */
  .modal-foot{ flex:none; display:flex; justify-content:flex-end;
    padding:var(--s5) var(--s7) var(--s7);
    border-top:1px solid var(--hair); background:var(--deep); }
  .modal-body p{ font-size:var(--fs-dense); color:var(--muted); line-height:1.7; }
  .modal-body p + p{ margin-top:var(--s4); }
  .modal-body b{ color:var(--white); font-weight:500; }

  @media(max-width:860px){
    /* the legal line is nowrap, so below this width it runs off the bar. It is
       in the footer, which is where a legal line belongs anyway. Without it the
       bar holds one group, which belongs on the side it was already on. */
    /* Two pages capped the section head here and one of them did it at 1040,
       so the same heading wrapped differently depending which page you were
       on. One rule, one breakpoint, every page.

       .sec-intro used to be in this list, on the reasoning that a line on a
       phone is as wide as the screen lets it be. True at 390, where the
       column is 335. From 600 to 860 the column is 605 to 765 and the cap
       was the only thing holding the line down, so switching it off ran the
       intro to 88 characters at 700, the worst measure on the site. A cap
       wider than its column does nothing on its own, so it never needed
       switching off. */
    .sec-title{ max-width:none; }
  }
  /* The nav has its own breakpoint, and 1100 is measured rather than chosen:
     the row needs 40 + 44 + 24 + 663 + 24 + 44 + 12 + 179 + 40, which is
     1070. It used to collapse at 1040, so from 1041 to 1069 every label broke
     to two lines, which the bar absorbed by growing to 70px. The bar is stated
     now and cannot grow, so the wrap would overflow it instead. 1100 leaves
     thirty pixels over what the row needs.

     It is its own block because 1040 belongs to the whole site: nine page
     stylesheets share it, so does the section head cap that was deliberately
     unified onto it, and so does the about portrait's `sizes`. The footer
     rules below stay on it. chrome.js carries the same 1100, because it is
     what decides which side of the breakpoint the primary action lives on. */
  @media(max-width:1100px){
    .nav-toggle{ display:flex; }
    /* The script moves the primary action out of the bar and into the menu,
       which is correct, but it runs at the end of the body: the bar has
       already been painted WITH the button in it, so the first thing a phone
       shows is a bar that then rearranges itself. Measured on 28 September at
       412px: the menu button jumped 158px sideways after load.
       Hiding it here means the bar is painted right the first time. The script
       still does the moving; this only decides what is visible while it is
       still in the bar, and once it is in the menu this selector no longer
       matches it. It costs nothing when the script is absent either, because
       the button opens a dialog that needs the script anyway. */
    .header-fixed .nav-right > .btn[data-open-contact]{ display:none; }
    .nav-links{ display:none; position:absolute; top:100%; left:0; right:0;
      flex-direction:column; gap:0; background:var(--surf-solid);
      border-bottom:1px solid var(--line); box-shadow:var(--shadow-lift); }
    .nav-links.open{ display:flex; }
    .nav-links a{ padding:var(--s5) var(--gutter);
      border-bottom:1px solid var(--hair-lo); font-size:var(--fs-small); }
    .nav-links a::after{ display:none; }
    .nav-links a:last-child{ border-bottom:0; }
    /* the primary action, moved here by the script, gets the full width and is
       the largest thing in the menu. The links above it have no border on the
       last one, so this supplies the divide. */
    .nav-links .btn{ margin:var(--s5) var(--gutter) var(--s6);
      width:calc(100% - 2 * var(--gutter)); }
    .nav-links a:last-of-type{ border-bottom:1px solid var(--hair-lo); }
  }
  @media(max-width:1040px){
    .foot-in{ grid-template-columns:1fr; }
    .foot-links{ align-items:flex-start; }
    .foot-mark svg{ height:44px; }
  }
  @media(max-width:600px){
    :root{ --gutter:var(--s5); --hdr:60px; --bar:60px; }
    /* next is the move, so on one column it goes first */
    .pager-in{ grid-template-columns:1fr; }
    .pg{ padding:var(--s6) var(--gutter); }
    .pg.next{ order:-1; align-items:flex-start; text-align:left; }
    .pg + .pg{ border-left:0; }
    .pg.prev{ border-top:1px solid var(--hair); }
    .cookie{ left:var(--s5); right:var(--s5); bottom:var(--s4); max-width:none;
      flex-wrap:nowrap; gap:var(--s3); padding:var(--s3) var(--s4); }
    .cookie span{ flex:1 1 auto; }
    .cookie-btns{ flex:0 0 auto; }
    .btn{ width:100%; }
    .wrap{ padding:var(--s11) var(--gutter); }
    .wrap.page-top{ padding-top:calc(var(--hdr) + var(--s9)); }
    .modal{ padding:0; align-items:flex-end; }
    /* A bottom sheet is right for a form and a notice, which are read from the
       top down and reached with a thumb. It is wrong for the drawing viewer,
       where the picture IS the content and belongs in the middle of the
       screen. This rule used to catch the lightbox too, so on a phone a tapped
       drawing sat jammed against the bottom edge with 593px of black above it
       and 16px below. Measured on a 412 by 823 screen, not guessed. */
    .modal.lightbox{ align-items:center; }
    /* 94vh inside an overlay that is now 100dvh tall would overflow it the
       moment the address bar is showing, and the overflow goes off the top,
       which is where the cross is. dvh for both or neither. */
    .modal-box{ max-width:none; max-height:94vh; max-height:94dvh;
      border-radius:var(--r-card) var(--r-card) 0 0; }
    .modal-head{ padding:var(--s6) var(--s5) var(--s5); }
    .mfields{ padding:var(--s5) var(--s5) var(--s2); }
    .mfoot{ padding:var(--s4) var(--s5) var(--s6); }
    /* .btn goes full width down here and .btn-ghost does not, which is right
       everywhere else on the site and wrong for the one control that gets a
       reader out of a full screen notice. Thumb width. */
    .modal-foot{ padding:var(--s4) var(--s5) var(--s6); }
    .modal-foot .btn-ghost{ width:100%; }
    .modal-body{ padding:var(--s5) var(--s5) var(--s6); }
    /* the card is full width down here, so the room it needs is its own height */
    body.cookie-up{ padding-bottom:var(--s12); }
    .cta-inner{ padding:var(--s8) var(--s5); }
    .cta-row{ gap:var(--s3) var(--s5); }
  }

