/* Cydora — page furniture: bands, the content column, the two-up grid,
   the nav and the footer. Structure that repeats, nothing section-specific. */

/* ---- layout ------------------------------------------------- */
.band { padding: clamp(4rem, 10vw, 8.5rem) var(--gut); }
.band--sand  { background: var(--sand); }
.band--deep  { background: var(--deep); }
.band--dark  { background: var(--band-dark); color: var(--band-dark-ink); }
.band--tight { padding-top: clamp(2.5rem, 6vw, 4rem); }

.wrap { max-width: var(--wrap); margin: 0 auto; }

.cols {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(2rem, 6vw, 5rem);
    align-items: start;
}

@media (max-width: 900px) {
    .cols { grid-template-columns: 1fr; }
}

/* ================================================================
   NAV
   ================================================================ */
.nav {
    position: sticky;
    top: 0;
    z-index: 50;
    /* Paper, not the wheat it used to be, and not transparent: the header is
       sticky, so whatever is under it scrolls behind it. Without a background
       the page would read straight through the logo and the links. Matching
       the paper is what makes it stop being a bar. */
    background: var(--paper);
    padding: 0 var(--gut);
}

.nav__inner {
    max-width: var(--wrap);
    margin: 0 auto;
    min-height: var(--nav-h);
    display: flex;
    align-items: center;
    gap: 2rem;
}

/* the lockup from cydora-nav/ lands here */
.nav__logo {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--display);
    font-size: 20px;
    letter-spacing: 0.06em;
    text-decoration: none;
    color: var(--ink);
}

/* Before the drawing arrives the slot is a small square placeholder; once
   nav.js has it, .nav__lockup below takes over the sizing. */
.nav__logo .slot {
    width: 26px;
    aspect-ratio: 1;
    border-color: rgba(37, 36, 34, 0.35);
    font-size: 0;
}

/* ---- the lockup -------------------------------------------------
   Scrolled to the top the header shows the mark and the word; past 15px it
   collapses to the mark alone. Two moves, deliberately out of step:

     closing  the letters fold away first, tail to head, and only once the
              word is gone does the box shut behind it (--q-word delay)
     opening  the reverse — the room is made first, then the letters land
              head to tail into it

   The box is a fixed-width window with overflow:hidden and the drawing keeps
   its full width inside, so what changes is how much of it you can see. That
   is why the svg below is sized in absolute units rather than 100%: shrinking
   the drawing itself would scale the mark down instead of hiding the word.

   All of it is CSS transitions. GSAP never touches this drawing, so opacity
   and scale are safe to declare here — the rule against that only applies to
   properties a scene animates.
   --------------------------------------------------------------- */
.nav__logo {
    --mark-h: 32px;                        /* the mark's own height        */
    --u: calc(var(--mark-h) / 175.622);    /* px per user unit             */
    --h: calc(var(--u) * 181.63);          /* padded box                   */
    --full: calc(var(--u) * 674.37);       /* mark + gap + word            */
    --icon: calc(var(--u) * 151.77);       /* clipped inside the gap, so no
                                              sliver of the C ever shows   */

    /* ---- the timings, declared here rather than on the lockup ----------
       They used to live on .nav__lockup, which is a child — and custom
       properties inherit downwards only. So the lockup could read them and
       the logo could not: `transition: translate ... var(--q-word)` on
       .nav__logo resolved --q-word to nothing, which makes the whole
       declaration invalid at computed-value time and drops it to `all`. The
       mark teleported instead of rolling, and nothing reported an error
       because an invalid var is not an error.

       Declared on the logo, the lockup still inherits every one of them, so
       its own rules are unchanged. */
    --ease: cubic-bezier(.65, 0, .35, 1);
    --morph: 300ms;                        /* the room the word needs      */
    --letter: 240ms;                       /* one letter landing           */
    --step: 40ms;
    --q-letter: 180ms;
    --q-step: 30ms;
    --q-morph: 260ms;
    --q-word: calc(5 * var(--q-step) + var(--q-letter));   /* word gone    */
}

/* The logo keeps the width of the whole lockup even when the word is hidden.
   Without this the flex row re-centres as the box narrows and the nav links
   slide across — the word disappearing should move nothing but the word. */
.nav__logo:has(.nav__lockup) {
    flex: none;
    width: var(--full);
}

.nav__logo .slot.nav__lockup {
    /* the timings are on .nav__logo now, and inherited down to here */
    flex: none;
    overflow: hidden;
    width: var(--full);
    height: var(--h);
    aspect-ratio: auto;

    /* Left-aligned, not centred. .slot centres its contents, which is right
       for a placeholder and wrong here: the box narrows to hide the word, and
       a centred drawing would slide left as it does, showing the middle of the
       lockup instead of the mark. The mark has to stay exactly where it is. */
    display: block;
}

/* Transitions only once the lockup has been in place for a frame, so the box
   does not visibly grow from the placeholder square on every page load. */
.nav__logo .slot.nav__lockup.is-ready {
    /* opening: make the room first, the letters land into it */
    transition: width var(--morph) var(--ease);
}

.nav__logo .slot.nav__lockup > svg {
    width: var(--full);      /* fixed — the wrapper is what clips */
    height: var(--h);
}

.nav__lockup.is-ready .nav-cls-4 {   /* the six letters */
    opacity: 1;
    scale: 1;
    transform-box: fill-box;
    transform-origin: center;
    /* expanding: letters land left to right, once the room is open */
    transition: opacity var(--letter) ease-out, scale var(--letter) ease-out;
    transition-delay: calc(var(--morph) + var(--li) * var(--step));
}

/* ---- collapsed, unless you are pointing at it ---------------------
   Past the first section the header shows the mark alone. Point at the logo —
   or reach it with a keyboard — and the word comes back, head to tail, and
   folds away again when you leave.

   Written as "collapsed AND not being pointed at" rather than as a hover rule
   that undoes a collapse rule. There is only one closed state and one open
   state, and the open one is the default further up this file: on hover these
   three selectors simply stop matching and the page falls back to it,
   opening transitions and letter stagger included. Nothing has to be
   re-declared, so nothing can drift out of step with its opposite.

   :focus-within, not :focus-visible — .nav__logo is the anchor itself, and it
   matches when the anchor has focus, so this is the keyboard's route in. */
/* No longer behind (hover: hover), so this is the behaviour on every screen.

   It was gated on the reasoning that the whole idea depends on being able to
   point at something — a touch screen has no hover, so the word would fold
   away and no gesture would bring it back, since tapping the logo follows the
   link. Half of that is right and the half that matters is not: `hover` is
   only one of the two ways out. The other is `data-collapsed` itself, which
   js/scenes/nav.js takes off again the moment the first section is back on
   screen. So on a phone the word is there at the top of the page, folds away
   as you leave the hero, and comes back when you scroll home — which is the
   same story the pointer tells, told by scrolling.

   What touch loses is the hover peek partway down the page. That is an
   enhancement rather than the feature, and `:not(:hover)` simply never stops
   matching there, so nothing has to be written twice. */
.nav[data-collapsed] .nav__logo:not(:hover):not(:focus-within) .nav__lockup {
    width: var(--icon);
}

.nav[data-collapsed] .nav__logo:not(:hover):not(:focus-within) .nav__lockup.is-ready {
    /* closing: the word leaves, then the room shuts behind it */
    transition: width var(--q-morph) var(--ease) var(--q-word);
}

.nav[data-collapsed] .nav__logo:not(:hover):not(:focus-within) .nav__lockup .nav-cls-4 {
    opacity: 0;
    scale: .92;
    /* collapsing: the tail of the word goes first, folding into the mark */
    transition: opacity var(--q-letter) ease-in, scale var(--q-letter) ease-in;
    transition-delay: calc((5 - var(--li)) * var(--q-step));
}

/* The logo's box never changes width, collapsed or not, so the links beside
   it do not move when the word comes and goes. Nothing to do here but say so:
   the width is on .nav__logo:has(.nav__lockup) above, and this is the reason
   it is there. */
.nav__logo { cursor: pointer; }

/* The footer wears this class too — one wordmark, styled once. Which means
   anything here that is about the *header's* lockup specifically, and below
   760px that is most of it, has to say `.nav .nav__logo` and not
   `.nav__logo`. Unscoped, the footer's copy was absolutely positioned on top
   of the address line beside it, and `pointer-events: none` took its link
   away as well: the `auto` that gives it back is on a lockup slot the footer
   does not have. */

@media (prefers-reduced-motion: reduce) {
    .nav__logo,
    .nav__logo .slot.nav__lockup,
    .nav__lockup .nav-cls-4 { transition: none; }
}

.nav__links {
    display: flex;
    gap: 2rem;
    margin: 0 auto;
    padding: 0;
    list-style: none;
}

/* ---- centred on the bar, not on what is left of it ---------------------
   `margin: 0 auto` above centres the list in a flex row, and that is not the
   same thing as centring it on the page. Auto margins take the *leftover*
   space, and the two sides of this row are not the same size: the logo is
   123px, while the theme switch and the call to action come to 319px with
   their gaps. The difference is 164px, so the list sat 82px left of the
   middle of the screen — centred, correctly, in the wrong box.

   Taking it out of the flow and centring it on .nav__inner fixes that,
   because .nav__inner is itself centred on the viewport (measured: +0). The
   `margin-left: auto` is the other half — with the list out of the flow there
   is nothing left holding the switch and the button over to the right, and
   they would pack in behind the logo.

   Only where there is room for it. The list is 324px wide, so it needs 162px
   either side of the middle, and the right-hand group needs 311px beyond
   that; below about 1080px those two start to overlap and the list goes back
   to taking the space that is actually free. Under 760px it is not in the bar
   at all — it is inside the drop-down. */
@media (min-width: 1080px) {
    .nav__inner { position: relative; }

    .nav__links {
        position: absolute;
        left: 50%;
        translate: -50%;
        margin: 0;
    }

    /* Nothing between the centred links and the call to action now that the
       theme switch has gone, so the button carries the auto margin that holds
       it against the right edge. .nav__cta, not .nav__panel .btn — the button
       moved out of the panel, and that selector had quietly stopped matching
       anything. */
    .nav__cta { margin-left: auto; }
}

/* The theme switch used to be here — an outlined disc that went crescent or
   solid depending on which way a click would take you. It moved to the debug
   dock (debug/panels/theme.js), so the whole block went with it. */

.nav__links a {
    display: inline-block;
    /* A 15px link in a flex row is an 18px target, which is under the 24px
       WCAG 2.5.8 asks for even with a mouse. The padding is vertical only, so
       the row's spacing is still the 2rem gap above and nothing moves — the
       header keeps its height from .nav__inner's min-height. */
    padding: 0.75rem 0;
    color: var(--ink);
    font-size: 15px;
    text-decoration: none;
    opacity: 0.85;
}

.nav__links a:hover { opacity: 1; text-decoration: underline; }

/* ---- the panel ------------------------------------------------------
   Wide: not a box at all. `display: contents` takes the div out of the layout
   and hands the links straight to .nav__inner's flex row, so the header
   measures exactly as it did before the wrapper existed. Below 760px it
   becomes the drop-down the burger opens — and now holds only the links,
   because the call to action stays in the bar. */
.nav__panel { display: contents; }

/* One label at a time. The short one is not an abbreviation — it is the same
   offer without the qualifier, because "diagnostic" is the word that will not
   fit a 375px bar. */
.nav__cta--short { display: none; }

/* ---- the burger -----------------------------------------------------
   Drawn, not fetched, for the same reason the theme switch is: three lines
   is a border and two shadows, and a file would be most of a request for
   fourteen pixels. The bar itself is the middle line; the shadows are the
   other two, and on open they fold into an X.

   44px square. That is the size a control has to be to be hit reliably with
   a thumb, and it is the number the rest of this file's touch rules use. */
.nav__burger {
    display: none;             /* below 760px this becomes inline-flex */
    flex: none;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin-right: -10px;       /* optical: the lines, not the box, align */
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--ink);
    cursor: pointer;
}

.nav__burger:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

.nav__burger i {
    position: relative;
    width: 20px;
    height: 1.5px;
    background: currentColor;
    /* the outer two lines */
    box-shadow: 0 -6px 0 currentColor, 0 6px 0 currentColor;
    transition: background .18s ease, box-shadow .18s ease;
}

/* Open: the middle line goes, and the other two come to the centre and
   cross. The shadows cannot rotate, so the two halves of the X are drawn as
   pseudo-elements and the shadows simply stop being painted. */
.nav[data-open] .nav__burger i {
    background: transparent;
    box-shadow: none;
}

.nav__burger i::before,
.nav__burger i::after {
    content: '';
    position: absolute;
    inset: 0;
    background: currentColor;
    opacity: 0;
    transition: opacity .18s ease, rotate .18s ease;
}

.nav[data-open] .nav__burger i::before { opacity: 1; rotate: 45deg; }
.nav[data-open] .nav__burger i::after  { opacity: 1; rotate: -45deg; }

@media (prefers-reduced-motion: reduce) {
    .nav__burger i,
    .nav__burger i::before,
    .nav__burger i::after { transition: none; }
}

/* ---- narrow ---------------------------------------------------------
   Three things in the bar, in the order a phone expects them: the menu on the
   left, the logo in the middle, the call to action on the right. The four
   links go into the drop-down the burger opens.

   The logo is centred on the *bar*, not on what is left between the burger
   and the button — those two are nothing like the same width, so an auto
   margin would put the mark visibly off centre. It is taken out of the flow
   and pinned to 50% instead, which is the same trick the links use above
   1080px, and for the same reason.

   That the logo moves is also why the hero's flight still lands: js/scenes/
   hero.js measures the nav logo's live box and derives the whole transform
   from it, so the lockup flies wherever the logo actually is.
   --------------------------------------------------------------------- */
@media (max-width: 760px) {
    .nav__inner {
        gap: 0.5rem;
        justify-content: space-between;
        position: relative;
    }

    .nav__burger { display: inline-flex; order: -1; margin-right: 0; }

    /* Centred — but the box is not the mark.

       .nav__logo keeps the width of the whole lockup whatever the word is
       doing, which is deliberate: it is what stops the links moving when the
       word folds away. The drawing inside is left-aligned in that box and the
       box narrows to --icon around it, so once the word has gone the *box* is
       still centred and the mark is sitting against its left edge, half a
       word off to one side.

       So the logo slides right by exactly the half-word it lost. Written from
       --full and --icon rather than as a measured number, so it stays true if
       the mark is ever resized: --mark-h is the only figure any of this comes
       from. */
    .nav .nav__logo {
        position: absolute;
        left: 50%;
        translate: -50%;
    }

    /* The mark slides right by the half-word it lost, and the curve is the
       whole of the character: a touch quick off the mark, a small overshoot,
       and a settle back. Forty-eight pixels is not far enough for anything
       more elaborate to read as anything but fidgeting — a full turn was
       tried here and it was a lot of motion for a very short journey.

       The overshoot is about four pixels. Enough to feel like the mark has
       weight and comes to rest, small enough that nobody would call it a
       bounce. */
    .nav .nav__logo {
        --roll: 460ms;
        --roll-ease: cubic-bezier(.34, 1.42, .64, 1);
    }

    .nav[data-collapsed] .nav__logo:not(:hover):not(:focus-within) {
        translate: calc(-50% + (var(--full) - var(--icon)) / 2);
    }

    /* Behind :has(.is-ready) for the reason the lockup's own transition is:
       until the drawing has been in place for a frame there is nothing to
       animate from, and without this the logo would roll across the bar on
       every page load. */
    .nav .nav__logo:has(.nav__lockup.is-ready) {
        /* opening: the room is made and the mark travels back into it */
        transition: translate var(--roll) var(--roll-ease);
    }

    .nav[data-collapsed]
    .nav .nav__logo:not(:hover):not(:focus-within):has(.nav__lockup.is-ready) {
        /* closing: the word folds away first — --q-word of delay — and only
           then does the mark set off, so what moves is a mark on its own and
           never a word being dragged sideways. */
        transition: translate var(--roll) var(--roll-ease) var(--q-word);
    }

    /* ---- what you can tap is what you can see -------------------------
       The logo keeps the width of the whole lockup even when only the mark is
       showing — that is what stops the bar reflowing as the word comes and
       goes. But it is also a positioned element, so it paints above the call
       to action beside it, and once it has slid right its empty half sits
       directly over the button's left edge. Tapping "Book a pilot" near its
       start went to the logo and scrolled the page to the top instead.

       So the anchor stops taking pointers and the lockup takes them instead.
       The lockup box *is* the visible artwork — --full open, --icon collapsed
       — so the target follows the drawing exactly, and the click still
       reaches the <a> by bubbling. */
    .nav .nav__logo { pointer-events: none; }
    .nav .nav__logo .slot.nav__lockup { pointer-events: auto; }

    /* Held against the right edge by the burger and the button being the only
       two things left in the flow. */
    .nav__cta { order: 1; }

    .nav__cta--long { display: none; }
    .nav__cta--short { display: block; }

    /* The bar is tight at 375px, so the button gives up some of its padding
       before it gives up being on one line. It keeps the 44px height a thumb
       needs — that comes from the padding-block, which is untouched. */
    .nav__cta.btn { padding-inline: 1rem; font-size: 14px; white-space: nowrap; }

    /* The wrapper stops being invisible and becomes the drop-down. .nav is
       sticky, which is a positioned element, so it is the containing block
       this hangs off — no extra wrapper needed to anchor it. */
    .nav__panel {
        display: block;
        position: absolute;
        left: 0;
        right: 0;
        top: 100%;
        padding: 0.25rem var(--gut) 1.5rem;
        background: var(--paper);
        border-bottom: 1px solid var(--rule);

        /* Closed. visibility, not display:none, so the panel has a state to
           transition out of and stays out of the tab order while shut. */
        visibility: hidden;
        opacity: 0;
        translate: 0 -0.5rem;
        transition: opacity .2s ease, translate .2s ease,
                    visibility 0s linear .2s;
    }

    .nav[data-open] .nav__panel {
        visibility: visible;
        opacity: 1;
        translate: none;
        transition: opacity .2s ease, translate .2s ease;
    }

    /* A list of rows, not a row of links. Each one is its own 48px band with
       a rule under it, which is both the target size and the affordance. */
    .nav__links {
        display: block;
        margin: 0;
    }

    .nav__links a {
        display: block;
        padding: 0.85rem 0;
        font-size: 17px;
        opacity: 1;
        border-bottom: 1px solid var(--rule);
    }

    .nav__links a:hover { text-decoration: none; }

}

@media (prefers-reduced-motion: reduce) {
    .nav__panel { transition: none; }
}

.footer { padding: 3rem var(--gut); }

.footer__inner {
    max-width: var(--wrap);
    margin: 0 auto;
    display: flex;
    flex-wrap: wrap;
    gap: 2rem;
    justify-content: space-between;
    align-items: flex-start;
}

.footer__meta { font-size: 14px; color: var(--muted); margin: 0.4rem 0 0; }

.footer__links {
    display: flex;
    flex-wrap: wrap;
    gap: 0 2rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.footer__links a {
    display: inline-block;
    /* A 15px link is an 18px target. The padding is what makes it 42, and it
       is vertical only so the row spacing below can stay the design's. */
    padding: 0.7rem 0;
    color: var(--muted);
    font-size: 15px;
    text-decoration: none;
}

.footer__links a:hover { color: var(--ink); }
