/* ==========================================================================
   BOOK OBWARD — the booking flow behind every "Book Obward" button
   --------------------------------------------------------------------------
   Two halves, deliberately different in temperature:

     1. The SPEC HALF (dark). Obward is a machine, and the CAD renders are
        lit on black, so the page opens dark and stays dark through the
        specs. Feature rows run down the left; the render column on the
        right is sticky, so one image holds while the reader moves through
        the rows beside it — the same device the reference Atlas page uses.

     2. The BOOKING HALF (light). Once the reader is deciding rather than
        reading, the page turns white: a form on the left, a live quote
        that sticks on the right.

   House rules apply throughout: no raw hex, no !important, no shadows on
   cards, square corners. Everything reads from tokens.css.

   Pricing lives in scripts/book-obward.js, not here — see the RATE CARD
   block at the top of that file to change a number.
   ========================================================================== */


/* ==========================================================================
   1. HERO
   ========================================================================== */

.ob-hero {
    padding: calc(var(--header-height) + var(--space-16)) 0 var(--space-16);
    background: var(--gradient-brand-deep);
    color: var(--on-inverse);
    overflow: hidden;
}

.ob-hero .container {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--space-10);
    align-items: center;
}

.ob-eyebrow {
    margin: 0 0 var(--space-4);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-normal);
    color: var(--on-inverse-faint);
}

.ob-hero h1 {
    margin: 0;
    font-size: var(--text-display);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tighter);
    line-height: var(--leading-tight);
    color: var(--on-inverse);
}

.ob-hero-lead {
    margin: var(--space-5) 0 0;
    max-width: var(--measure-tight);
    font-size: var(--text-lead);
    font-weight: var(--weight-normal);
    line-height: var(--leading-relaxed);
    color: var(--on-inverse-soft);
}

.ob-hero-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space-4);
    margin-top: var(--space-8);
}

/* The headline price, sat under the buttons so the number is answered
   before the reader has to go looking for it. */
.ob-hero-from {
    margin: var(--space-8) 0 0;
    font-size: var(--text-sm);
    color: var(--on-inverse-faint);
}

.ob-hero-from strong {
    display: block;
    margin-bottom: var(--space-1);
    font-size: var(--text-3xl);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tight);
    color: var(--on-inverse);
}

/* --- the renders ---------------------------------------------------- */

/* The renders arrive from CAD as a lit grey model on solid black. The black
   is keyed out in the asset itself — flood-filled from the frame edges, so
   the dark optics inside the model survive — and each file is cropped to the
   head. That means real alpha rather than a mix-blend-mode trick: it needs no
   particular background behind it, survives any stacking context, and cannot
   fail open into a black rectangle. */
.ob-render {
    display: block;
    width: 100%;
    height: auto;
}

.ob-hero-figure {
    margin: 0;
}


/* ==========================================================================
   2. SPEC SECTION

   Left: a stack of feature rows. Right: a sticky column of renders.
   ========================================================================== */

.ob-specs {
    padding: var(--space-24) 0;
    background: var(--brand-ink-deep);
    color: var(--on-inverse);
}

.ob-specs-head {
    max-width: 640px;
    margin: 0 auto var(--space-20);
    text-align: center;
}

.ob-specs-head h2 {
    margin: 0;
    font-size: var(--text-display);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tighter);
    line-height: var(--leading-tight);
    color: var(--on-inverse);
}

.ob-specs-head p {
    margin: var(--space-5) auto 0;
    max-width: var(--measure-tight);
    font-size: var(--text-base);
    line-height: var(--leading-relaxed);
    color: var(--on-inverse-soft);
}

.ob-specs-head a {
    color: var(--on-inverse);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.ob-specs-grid {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: clamp(var(--space-10), 6vw, var(--space-24));
    align-items: start;
}

/* --- the feature rows ---------------------------------------------- */

.ob-feature {
    padding: var(--space-8) 0;
    /* Hairline between rows only, never around them — matches the
       divider-not-border rule the products page sets. */
    border-top: 1px solid var(--on-inverse-line);
}

.ob-feature:first-child {
    border-top: 0;
    padding-top: 0;
}

.ob-feature h3 {
    margin: 0 0 var(--space-3);
    font-size: var(--text-xl);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tight);
    color: var(--on-inverse);
}

.ob-feature p {
    margin: 0;
    font-size: var(--text-sm);
    line-height: var(--leading-relaxed);
    color: var(--on-inverse-soft);
}

/* Three facts under each row. A definition list, because that is what it
   is — label above value, as on the reference page. */
.ob-feature-specs {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-5);
    margin: var(--space-6) 0 0;
}

.ob-feature-specs dt {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-normal);
    color: var(--on-inverse);
}

.ob-feature-specs dd {
    margin: var(--space-2) 0 0;
    font-size: var(--text-sm);
    line-height: var(--leading-snug);
    color: var(--on-inverse-soft);
}

/* --- the render column --------------------------------------------- */

.ob-specs-media {
    position: sticky;
    /* Clears the fixed header plus a little air. */
    top: calc(var(--header-height) + var(--space-8));
}

.ob-specs-media figure {
    margin: 0;
}

/* Without the script the three renders simply stack and scroll: nothing is
   hidden, nothing depends on JS. book-obward.js adds .is-stacked, which
   collapses them into one frame that cross-fades as each feature row comes
   up — the sticky column has to fit in a viewport for stickiness to mean
   anything, and three full-height figures do not. */
.ob-render-stack {
    display: flex;
    flex-direction: column;
    gap: var(--space-6);
}

.ob-render-stack.is-stacked {
    display: grid;
    /* One cell, every frame in it. A fixed box stops the column resizing as
       renders of slightly different proportions swap through it. */
    grid-template-areas: 'render';
    aspect-ratio: 5 / 4;
}

.ob-render-stack.is-stacked .ob-render-frame {
    grid-area: render;
    display: flex;
    flex-direction: column;
    justify-content: center;
    opacity: 0;
    transition: opacity var(--duration-slow) var(--ease);
}

.ob-render-stack.is-stacked .ob-render-frame.is-active {
    opacity: 1;
}

.ob-render-stack.is-stacked .ob-render {
    max-height: 100%;
    object-fit: contain;
}

@media (prefers-reduced-motion: reduce) {
    .ob-render-stack.is-stacked .ob-render-frame {
        transition: none;
    }
}


/* ==========================================================================
   3. BOOKING

   Form left, live quote right. The quote sticks so the number stays on
   screen while the form is filled in.
   ========================================================================== */

.ob-booking {
    padding: var(--section-y) 0;
    background: var(--surface-sunken);
}

.ob-booking-head {
    max-width: var(--measure);
    margin: 0 0 var(--space-12);
}

.ob-booking-head h2 {
    margin: 0;
    font-size: var(--text-display-sm);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tighter);
    line-height: var(--leading-tight);
    color: var(--ink-strong);
}

.ob-booking-head p {
    margin: var(--space-4) 0 0;
    font-size: var(--text-lg);
    line-height: var(--leading-relaxed);
    color: var(--ink-soft);
}

.ob-booking-grid {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    gap: var(--space-8);
    align-items: start;
}

/* --- form ----------------------------------------------------------- */

.ob-form {
    padding: var(--space-8);
    background: var(--surface);
}

.ob-fieldset {
    margin: 0 0 var(--space-10);
    padding: 0;
    border: 0;
}

.ob-fieldset:last-of-type {
    margin-bottom: var(--space-8);
}

.ob-fieldset legend {
    display: block;
    width: 100%;
    padding: 0 0 var(--space-5);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-normal);
    color: var(--ink-faint);
}

.ob-row {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-5);
    margin-bottom: var(--space-5);
}

.ob-row--single {
    grid-template-columns: minmax(0, 1fr);
}

.ob-field {
    display: flex;
    flex-direction: column;
}

.ob-field label {
    margin-bottom: var(--space-2);
    font-size: var(--text-sm);
    font-weight: var(--weight-medium);
    color: var(--ink);
}

.ob-field input,
.ob-field select,
.ob-field textarea {
    width: 100%;
    padding: var(--space-3) var(--space-4);
    border: 1px solid var(--line);
    border-radius: 0;
    background: var(--surface);
    font-family: var(--font-sans);
    font-size: var(--text-base);
    color: var(--ink);
    transition: var(--transition-colors), box-shadow var(--duration-base) var(--ease);
}

.ob-field textarea {
    min-height: 110px;
    resize: vertical;
}

.ob-field input:focus,
.ob-field select:focus,
.ob-field textarea:focus {
    outline: none;
    border-color: var(--brand);
    box-shadow: var(--shadow-focus);
}

.ob-field-note {
    margin: var(--space-2) 0 0;
    font-size: var(--text-xs);
    color: var(--ink-faint);
}

/* The date inputs get their own note when the range is wrong. Hidden until
   the script fills it, so it never occupies space it is not using. */
.ob-field-error {
    margin: var(--space-2) 0 0;
    font-size: var(--text-xs);
    color: var(--danger);
}

.ob-field-error:empty {
    display: none;
}

/* A field the submit handler rejected. Colour alone would not carry the
   message, which is why the panel prints one too — this is the pointer to
   which field it means. */
.ob-field :is(input, select, textarea)[aria-invalid='true'] {
    border-color: var(--danger);
}

/* --- radio cards (package, location) -------------------------------- */

.ob-choices {
    display: grid;
    gap: var(--space-3);
    margin-bottom: var(--space-5);
}

.ob-choices--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ob-choices--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.ob-choice {
    position: relative;
    display: block;
    padding: var(--space-5);
    border: 1px solid var(--line);
    cursor: pointer;
    transition: var(--transition-colors);
}

.ob-choice:hover {
    border-color: var(--ink-faint);
}

/* The input is the state, the label is the surface. Kept in the flow but
   visually hidden so it stays focusable and reachable by the arrow keys. */
.ob-choice input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

.ob-choice:has(input:checked) {
    border-color: var(--brand);
    background: var(--brand-tint);
}

.ob-choice:has(input:focus-visible) {
    box-shadow: var(--shadow-focus);
}

.ob-choice-name {
    display: block;
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-snug);
    color: var(--ink-strong);
}

.ob-choice-meta {
    display: block;
    margin-top: var(--space-1);
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--ink-soft);
}

.ob-choice-price {
    display: block;
    margin-top: var(--space-3);
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--brand);
}

/* --- add-on checkboxes ---------------------------------------------- */

.ob-addon {
    display: grid;
    grid-template-columns: 20px minmax(0, 1fr) auto;
    gap: var(--space-4);
    align-items: baseline;
    padding: var(--space-4) 0;
    border-top: 1px solid var(--line-soft);
    cursor: pointer;
}

.ob-addon:first-of-type {
    border-top: 0;
}

.ob-addon input {
    width: 18px;
    height: 18px;
    accent-color: var(--brand);
}

.ob-addon-name {
    font-size: var(--text-sm);
    color: var(--ink);
}

.ob-addon-name small {
    display: block;
    margin-top: var(--space-1);
    font-size: var(--text-xs);
    color: var(--ink-faint);
}

.ob-addon-price {
    font-size: var(--text-sm);
    font-weight: var(--weight-semibold);
    color: var(--ink-soft);
}

/* --- quote ----------------------------------------------------------- */

.ob-quote {
    position: sticky;
    top: calc(var(--header-height) + var(--space-6));
    padding: var(--space-8);
    background: var(--surface);
    color: var(--ink);
}

.ob-quote h3 {
    margin: 0 0 var(--space-2);
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-normal);
    color: var(--ink-faint);
}

/* The summary line the script keeps up to date: event, company, dates. */
.ob-quote-for {
    margin: 0 0 var(--space-6);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--ink-soft);
}

.ob-quote-lines {
    margin: 0;
    padding: 0;
    list-style: none;
}

.ob-quote-lines li {
    display: flex;
    justify-content: space-between;
    gap: var(--space-4);
    padding: var(--space-3) 0;
    font-size: var(--text-sm);
    border-top: 1px solid var(--line-soft);
}

.ob-quote-lines li:first-child {
    border-top: 0;
}

.ob-quote-lines .ob-quote-label {
    color: var(--ink-soft);
}

.ob-quote-lines .ob-quote-value {
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
    color: var(--ink-strong);
}

.ob-quote-total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--space-4);
    margin-top: var(--space-5);
    padding-top: var(--space-5);
    border-top: 1px solid var(--line);
}

.ob-quote-total dt {
    font-size: var(--text-xs);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-normal);
    color: var(--ink-faint);
}

.ob-quote-total dd {
    margin: 0;
    font-size: var(--text-4xl);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tight);
    font-variant-numeric: tabular-nums;
    color: var(--ink-strong);
}

.ob-quote-fine {
    margin: var(--space-5) 0 0;
    font-size: var(--text-xs);
    line-height: var(--leading-normal);
    color: var(--ink-faint);
}

/* Sits above the submit button, on the white quote panel, so the standard
   danger colour on its tinted band reads correctly. */
.ob-error {
    margin: var(--space-5) 0 0;
    padding: var(--space-3) var(--space-4);
    background: var(--danger-bg);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--danger);
}

.ob-error:empty {
    display: none;
}

.ob-submit {
    display: block;
    width: 100%;
    margin-top: var(--space-6);
    padding: var(--space-4) var(--space-6);
    border: 0;
    border-radius: 0;
    background: var(--brand);
    color: var(--on-inverse);
    font-family: var(--font-sans);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-snug);
    text-align: center;
    cursor: pointer;
    transition: var(--transition-colors);
}

.ob-submit:hover {
    background: var(--brand-dark);
}

.ob-submit:focus-visible {
    outline: none;
    box-shadow: var(--shadow-focus);
}

/* Confirmation, swapped in by the script once the request is handed off to
   the mail client. Hidden until then. */
.ob-sent {
    margin: var(--space-5) 0 0;
    padding: var(--space-4);
    background: var(--brand-tint-strong);
    font-size: var(--text-sm);
    line-height: var(--leading-normal);
    color: var(--brand-dark);
}

.ob-sent:empty {
    display: none;
}


/* ==========================================================================
   4. WHAT ARRIVES — the closing band
   ========================================================================== */

.ob-includes {
    padding: var(--section-y) 0;
    background: var(--surface);
}

.ob-includes h2 {
    margin: 0 0 var(--space-10);
    font-size: var(--text-display-sm);
    font-weight: var(--weight-semibold);
    letter-spacing: var(--tracking-tighter);
    line-height: var(--leading-tight);
    color: var(--ink-strong);
}

.ob-includes-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--space-8);
}

.ob-include h3 {
    margin: 0 0 var(--space-3);
    font-size: var(--text-base);
    font-weight: var(--weight-semibold);
    color: var(--ink-strong);
}

.ob-include p {
    margin: 0;
    font-size: var(--text-sm);
    line-height: var(--leading-relaxed);
    color: var(--ink-soft);
}


/* ==========================================================================
   5. GRAIN BEHIND THE CONTENT

   patterns.css paints .grain::after at z-index 1 — above the section's
   background but also above everything in it, so copy, form fields and the
   head renders all sit under a noise layer. On this page the texture belongs
   to the surface alone.

   Isolating each band gives the pseudo-element a stacking context of its own;
   a negative z-index inside one paints above that element's background and
   below its in-flow content, which is exactly the slot we want. The blend
   still has the band's background to work against, so the grain reads as
   before — it just stops falling over the words.
   ========================================================================== */

.ob-hero,
.ob-specs,
.ob-booking,
.ob-includes,
.footer.grain {
    isolation: isolate;
}

.ob-hero.grain::after,
.ob-specs.grain::after,
.ob-booking.grain::after,
.ob-includes.grain::after,
.footer.grain::after {
    z-index: -1;
}


/* ==========================================================================
   6. RESPONSIVE

   Two breaks, not five: the point where the two-column bands stop fitting,
   and the point where paired fields stop fitting.
   ========================================================================== */

@media (max-width: 980px) {
    .ob-hero .container,
    .ob-specs-grid,
    .ob-booking-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    /* The render leads on a narrow screen, as it does on the products page —
       a column of text with an image stranded below it reads as an
       afterthought. */
    .ob-hero-figure { order: -1; }

    /* Nothing to stick to once the columns stack. */
    .ob-specs-media,
    .ob-quote {
        position: static;
    }

    /* Stacked columns means the renders now sit above the feature rows they
       illustrate, so swapping one frame for another as you scroll no longer
       lines up with anything. All three go back to being visible at once,
       side by side. The script's .is-stacked is overridden rather than
       skipped, because a resize can cross this line after it has run. */
    .ob-render-stack.is-stacked {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        grid-template-areas: none;
        gap: var(--space-4);
        aspect-ratio: auto;
    }

    .ob-render-stack.is-stacked .ob-render-frame {
        grid-area: auto;
        opacity: 1;
    }

    .ob-includes-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

@media (max-width: 640px) {
    .ob-row,
    .ob-choices--2,
    .ob-choices--3,
    .ob-feature-specs,
    .ob-render-stack.is-stacked,
    .ob-includes-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .ob-specs {
        padding: var(--space-16) 0;
    }

    .ob-form,
    .ob-quote {
        padding: var(--space-6);
    }

    .ob-hero-actions .btn-sweep {
        width: 100%;
    }
}
