/**
 * Hand-maintained hardening for the de-iframed (native) configurators.
 *
 * Loaded AFTER the generated assets/configurators-native/{type}.css, so it can
 * correct the few things that only break once the app lives in the page instead
 * of an iframe. Kept in its own file so regenerating the bundles never wipes it.
 *
 * @package Wyne
 */

/* The design's body sets no font-size, so the configurator was authored at the
   browser default of 16px/normal. Our global body is 17px/1.6, which cascaded
   in once the app stopped living in an iframe and made every inheriting block a
   little taller (measured: showcase +53px, cards +20px on the desktop design). */
.wyne-cfg { font-size: 16px; line-height: normal; }

/* Inside an iframe the document itself clipped overflow; in the page a wide flex
 * child (the 4-step stepper: 4×110px dots + 3×100px separators ≈ 740px) instead
 * stretched the whole layout, so on phones the hero title and the bottle card ran
 * off-screen. Flex/grid children default to min-width:auto, which defeats the
 * design's own `overflow-x:auto` on the stepper — pin them to 0 and clip. */
.config-product--native { max-width: 100%; overflow-x: clip; }
.config-product--native .wyne-cfg { max-width: 100%; }

/* Step 1 upload / recording UI (assets/js/configurator-sound.js). The compiled
 * configurators only styled the three choice cards, so this is ours. */
.wyne-sound-ui { margin-top: 18px; display: flex; flex-direction: column; gap: 12px; }
/* The record button itself is the bundle's own (.record-btn); only the elapsed
   time next to it is ours. */
.wyne-cfg .wyne-rec-time { font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 12px; opacity: .8; margin-left: 14px; }
.wyne-sound-ui .wyne-sound-msg { font-family: 'Cormorant Garamond', serif; font-style: italic; font-size: 15px; opacity: .9; }
.wyne-sound-ui .wyne-sound-msg[data-error="1"] { color: #b5432b; font-style: normal; }
.wyne-sound-ui audio.wyne-sound-preview { width: 100%; max-width: 420px; }

/* Absolutely-positioned decorations must resolve against their own element, not
 * some far ancestor — otherwise e.g. the active proof tab's 2px gold underline
 * escapes and draws a full-width gold line across the hero. */
.wyne-cfg .tab,
.wyne-cfg .panel,
.wyne-cfg .card,
.wyne-cfg .band,
.wyne-cfg .stage { position: relative; }

@media (max-width: 980px) {
  .wyne-cfg .stepper { min-width: 0; max-width: 100%; }
  .wyne-cfg .stage,
  .wyne-cfg .stage > *,
  .wyne-cfg .hero-grid-band,
  .wyne-cfg .panel,
  .wyne-cfg .showcase { min-width: 0; }
  /* Long words / prices shouldn't force a wider line box on narrow screens. */
  .wyne-cfg .hero h1,
  .wyne-cfg .panel-head h2 { overflow-wrap: anywhere; }
}

/* The de-iframe reset gave the wrapper `isolation: isolate` to keep the bundle's
 * z-indexes to itself. That also traps the preview overlay: it asks for z-index
 * 100 but, sealed inside a stacking context that sits at 0, it painted under the
 * sticky header (50). Let the wrapper share the page's stacking and lift the
 * overlay above the chrome instead. */
.wyne-cfg { isolation: auto; }
.wyne-cfg .overlay,
.wyne-cfg .preview-overlay,
.wyne-cfg #previewOverlay { z-index: 120; }

/* A YouTube link is one unbreakable token; in the preview's summary column it
 * pushed the card wider than a phone screen, which is what shifted the bottle
 * image off to the left and clipped the text on the right. */
.wyne-cfg .pd-row .v,
.wyne-cfg .preview-detail .v { overflow-wrap: anywhere; word-break: break-word; min-width: 0; }
.wyne-cfg .pd-row { min-width: 0; }

/* The wedding shell carries the proof block in its .pf-* form, while the
 * compiled CSS only declares the palette on .pf2 — so var(--pf-muted) resolved
 * to nothing there and the labels inherited dark ink onto a near-black panel.
 * Declare the same tokens on the .pf-* root. */
.wyne-cfg .pf-shell {
  --pf-bg1: #1c1610; --pf-bg2: #16110b;
  --pf-gold: #c9a44c; --pf-gold-soft: #e6cf9e;
  --pf-ink: #f5ede0; --pf-body: #c7bba8; --pf-muted: #8e8474;
  --pf-panel: #15110c; --pf-line: rgba(231,210,176,0.14);
}

/* The drop zone is a real drop target now (assets/js/configurator-sound.js):
 * the whole zone is clickable and a dragged file highlights it. */
.wyne-cfg .upload-zone { cursor: pointer; transition: border-color .2s, background .2s; }
.wyne-cfg .upload-zone.is-dragover {
  border-color: var(--green, #1f3522);
  background: rgba(31, 53, 34, 0.05);
}

/* home-v2.css ships a global `.sub` — the homepage's 380px dark subscription
 * card, complete with a 2px gold hairline as ::after. Inside a configurator
 * `.sub` is just a line of text (the hero paragraph, the "one bottle, made for
 * you" line under TOTAL WAIT, the card subtitles), so the box and the hairline
 * have to go; the bundles style the text themselves. */
.wyne-cfg .sub {
  border: 0;
  padding: 0;
  min-height: 0;
  background: none;
  overflow: visible;
  display: block;
}
.wyne-cfg .sub::after { content: none; }

/* The phone layer bleeds the tinted panel head past the gutter with a fixed
 * -20px margin, which assumes the design's own 20px panel padding. Our panel has
 * none, so the band ended up 4px wider than the screen on each side — enough to
 * drag the page sideways. Bleed to the viewport instead, which cannot overflow. */
@media (max-width: 860px) {
  /* The generated phone layer sets this under body.m-started and loads after
     this file, so it needs one more class here to be overridden. */
  body.m-started .wyne-cfg.wyne-cfg.wyne-cfg.wyne-cfg .panel-head,
  .wyne-cfg.wyne-cfg.wyne-cfg.wyne-cfg .panel-head {
    /* the stage's phone gutter, so the band reaches the screen edges exactly */
    margin-left: -16px;
    margin-right: -16px;
    width: auto;
    max-width: none;
  }
}

/* ---------------------------------------------------------------------------
 * Room under the wizard — exactly the design's.
 *
 * The design gives .stage `margin: 24px auto 64px`, and that 64px is all the
 * space there is under the Add to cart panel. On the site that bottom margin
 * collapsed straight out of the wrapper (nothing separates them), so the wizard
 * sat flush against the black footer. flow-root keeps the margin inside, which
 * gives the design's 64px — no extra padding on top of it.
 * ------------------------------------------------------------------------- */
.config-product .wyne-cfg.embedded { display: flow-root; padding-bottom: 0; }

/* ---------------------------------------------------------------------------
 * The design's paper texture.
 *
 * The configurator page draws a fine gold grid over the parchment (body::before
 * in the design). De-iframing turned that pseudo-element into a class selector
 * that matches nothing, so the background came out flat.
 * ------------------------------------------------------------------------- */
.wyne-cfg.embedded { position: relative; }
.wyne-cfg.embedded::before {
  content: "";
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    repeating-linear-gradient(0deg, transparent 0 13px, rgba(138,111,51,0.05) 13px 14px),
    repeating-linear-gradient(90deg, transparent 0 13px, rgba(138,111,51,0.05) 13px 14px);
}
/* The grid sits behind the content — but never re-position an overlay: the
   preview is `position: fixed`, and making it relative dropped it into the
   page flow instead of opening as a modal. */
.wyne-cfg.embedded > *:not(.overlay) { position: relative; z-index: 1; }
.wyne-cfg.embedded > .overlay { z-index: 2000; }

/* The phone flow wraps the wizard AND its overlays, so the z-index above turned
   .m-flow into a stacking context and sealed the preview inside it at 1 — the
   modal asked for 2000 and still painted under the header. It keeps position
   (the grid needs it) and gives up the index; on a phone the flow layer sets
   its own fixed/300, which is what that state wants. */
.wyne-cfg.embedded > .m-flow { z-index: auto; }

/* ---------------------------------------------------------------------------
 * Preview slideshow: the frame has to be the size of its photo.
 *
 * The showcase's `.bottle-frame` is `width: 100%` — right there, wrong in the
 * preview, where the slide rule only re-declares `display: inline-block` and
 * the 100% carried over. The label closeup is narrower than the stage, so its
 * frame stayed full width: the photo sat against the left edge, and the
 * overlay (positioned in % of the frame) printed the label text off-centre
 * with it. Sizing the frame to the photo fixes both.
 * ------------------------------------------------------------------------- */
.wyne-cfg .pv-bottle .bottle-frame {
  width: auto;
  margin-left: auto;
  margin-right: auto;
}

/* ---------------------------------------------------------------------------
 * The phone's intro card and its close button — hidden everywhere else.
 *
 * The design hides them in its base stylesheet and shows them inside the
 * phone media query. Ours only loads the phone layer under 860px, so on a
 * desktop those rules were never applied at all and the card rendered raw
 * under the hero. Hide them here, where the stylesheet always loads; the
 * phone layer turns them back on.
 * ------------------------------------------------------------------------- */
.wyne-cfg .m-intro,
.wyne-cfg .m-flow-close { display: none; }

@media (max-width: 760px) {
  .wyne-cfg .m-intro { display: block; }
  body.m-started .wyne-cfg .m-intro { display: none; }
  body.m-started .wyne-cfg .m-flow-close { display: flex; }
}


/* ---------------------------------------------------------------------------
 * The heartbeat's "Click here!" only opened from its left half.
 *
 * The build listens with `e.target.id === 'hbHelpOpen'`, so a click that lands
 * on the emphasised <span> inside the button never matches — only the button's
 * own text did. Taking the span out of hit-testing makes the button the target
 * wherever you click it.
 * ------------------------------------------------------------------------- */
.wyne-cfg .hb-help-cta span { pointer-events: none; }

/* ---------------------------------------------------------------------------
 * The preview opens over everything.
 *
 * It is the whole screen, so the site header — and the notification strip
 * above it — must not sit on top of it.
 * ------------------------------------------------------------------------- */
.wyne-cfg .overlay,
.wyne-cfg .preview-overlay,
.wyne-cfg #previewOverlay { z-index: 2000; }
body.wyne-preview-open .topbar,
body.wyne-preview-open .artist-bar { z-index: 1; }

/* The design's own file player (the vows build draws it; Signature and the
   artist bottle have no such card of their own, so the same rules are kept
   here rather than a second look being invented for them). */
.upload-zone.has-file,
.upload-zone.has-file .hb-player {
    --gold-deep: var(--cfg-gold-deep, #8a6f33);
    --green: var(--cfg-green, #1f3522);
    --ink: var(--cfg-ink, #261e10);
    --ink-mute: var(--cfg-ink-mute, #7a6f5a);
    --line-strong: var(--cfg-line-strong, rgba(38, 30, 16, 0.22));
    --paper: var(--cfg-paper, #ffffff);
    --red: var(--cfg-red, #b53a2a);
  }
/* The artist bottle is an ember-dark build, so its card takes the build's own
   colours rather than the pale ones the vows card is drawn in. */
.wyne-cfg--artist .upload-zone.has-file,
.wyne-cfg--artist .upload-zone.has-file .hb-player {
    --green: rgba(193, 90, 58, .55);
    --ink: #faeee8;
    --ink-mute: rgba(250, 238, 232, .62);
    --line-strong: rgba(224, 150, 106, .3);
    --paper: #1e150f;
  }
.upload-zone.has-file {
    padding: 0;
    background: var(--paper);
    border-style: solid;
    border-color: var(--green);
    cursor: default;
  }
.upload-zone.has-file:hover { border-color: var(--green); background: var(--paper); }
.hb-player {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 18px;
    padding: 18px 22px;
    text-align: left;
    width: 100%;
  }
.hb-player-controls {
    display: flex; gap: 8px; align-items: center;
  }
.hb-pbtn {
    width: 40px; height: 40px;
    border-radius: 50%;
    background: var(--green); color: var(--paper);
    border: 1.5px solid var(--green);
    display: grid; place-items: center;
    cursor: pointer; padding: 0;
    transition: transform 0.15s, background 0.15s, box-shadow 0.15s;
    flex-shrink: 0;
  }
.hb-pbtn:hover:not(:disabled) { transform: scale(1.06); box-shadow: 0 4px 14px rgba(31, 53, 34, 0.25); }
.hb-pbtn.stop {
    width: 34px; height: 34px;
    background: transparent; color: var(--ink-mute);
    border-color: var(--line-strong);
  }
.hb-pbtn.stop:hover:not(:disabled) { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.hb-pbtn:disabled { opacity: 0.35; cursor: not-allowed; }
.hb-pbtn.play.is-playing {
    background: var(--gold-deep); border-color: var(--gold-deep);
  }
.hb-player-body { min-width: 0; }
.hb-player-name {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 12px; margin-bottom: 8px;
  }
.hb-player-name .fn {
    font-family: var(--serif); font-style: italic; font-size: 15px;
    color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
.hb-player-name .meta {
    font-size: 9px; letter-spacing: 0.25em; text-transform: uppercase;
    color: var(--gold-deep); flex-shrink: 0;
  }
.hb-player-wave {
    position: relative;
    display: flex; align-items: center; gap: 2px;
    height: 36px;
    padding: 4px 0;
  }
.hb-player-wave .hb-w-bar {
    flex: 1; min-width: 2px;
    background: var(--gold-deep); opacity: 0.45;
    border-radius: 1px;
    transition: opacity 0.15s, background 0.15s, transform 0.15s;
    transform-origin: center;
  }
.hb-player-wave.is-playing .hb-w-bar {
    background: var(--green); opacity: 0.7;
    animation: hb-bar-pulse 1.2s ease-in-out infinite;
  }
.hb-player-wave.is-playing .hb-w-bar:nth-child(6n+1) { animation-delay: -0.0s; }
.hb-player-wave.is-playing .hb-w-bar:nth-child(6n+2) { animation-delay: -0.2s; }
.hb-player-wave.is-playing .hb-w-bar:nth-child(6n+3) { animation-delay: -0.4s; }
.hb-player-wave.is-playing .hb-w-bar:nth-child(6n+4) { animation-delay: -0.6s; }
.hb-player-wave.is-playing .hb-w-bar:nth-child(6n+5) { animation-delay: -0.8s; }
.hb-player-wave.is-playing .hb-w-bar:nth-child(6n+6) { animation-delay: -1.0s; }
.hb-player-wave.is-playing .hb-w-cursor {
    opacity: 1;
    animation: hb-cursor-move 42s linear forwards;
  }
.hb-player-times {
    display: flex; justify-content: space-between;
    margin-top: 4px;
    font-family: var(--sans); font-weight: 500;
    font-size: 10px; letter-spacing: 0.2em;
    color: var(--ink-mute);
  }
.hb-player-times .now { color: var(--green); font-variant-numeric: tabular-nums; }
.hb-player-times .dur { color: var(--gold-deep); }
.hb-player-remove {
    background: transparent;
    border: 1px solid transparent;
    padding: 8px 12px;
    color: var(--ink-mute);
    font-family: var(--sans); font-size: 10px;
    letter-spacing: 0.22em; text-transform: uppercase;
    cursor: pointer;
    display: inline-flex; align-items: center; gap: 6px;
    transition: all 0.15s;
    flex-shrink: 0;
    align-self: stretch;
  }
.hb-player-remove:hover {
    color: var(--red); border-color: var(--red);
  }
.hb-player { grid-template-columns: auto 1fr; grid-template-rows: auto auto; }
.hb-player-remove { grid-column: 1 / -1; justify-self: flex-end; }

/* home-v2.css carries a bare `.panel-head { max-width: 64ch }` for the homepage
   band, and it reached inside the wizard too: the step's heading stopped 100px
   short of the cards under it. The proof section keeps its own measure. */
.wyne-cfg .panel > .panel-head,
.wyne-cfg #panel > .panel-head { max-width: none; }
