/* Shared Buzz builder shell: split-panel layout (accordion form left, live preview right),
   a draggable width-adjuster between them, and the accordion/wizard step styling. Ported
   from ResumeBuzz's builder (buzzresume.com/build/, the proven reference) and made brand-
   agnostic: every color below reads a CSS custom property the including page defines in its
   own <style> block, nothing here is hardcoded to one brand's palette.
   Required vars on the including page's :root: --bg --surface --surface2 --ink --muted
   --warm --border --accent --accent-dark --field-bg --field-border --emboss-lt --emboss-dk
   Phase 5 (mighty-twirling-micali.md): all four Buzz builders converge on this one shell.
   BuzzExec is the first brand built against it; ResumeBuzz/GradBuzz's own inline copies of
   this same layout get replaced with this file later in the sequence, not rewritten twice. */

html,body{height:100%;overflow:hidden}
body{margin:0;display:flex;flex-direction:column}

.bshell-main{flex:1;display:flex;overflow:hidden;min-height:0}

/* LEFT PANEL: the accordion form. Width is a CSS var so the resizer can drag it live. */
.left-panel{
  width:var(--bshell-left-w, 420px);
  flex-shrink:0;
  border-right:2px solid var(--border);
  overflow-y:auto;
  display:flex;
  flex-direction:column;
  position:relative;
  background-color:var(--surface);
  background-repeat:repeat;
  background-size:72px 41.569px;
  background-attachment:local;
}
/* Light honeycomb texture, 2026-08-27 -- Blake: "I do like the hex background of the left
   column though, let's apply a light honeycomb texture to all four builders." Same hex-grid
   SVG as BuzzResume's own left-panel (its build/index.html, the original this shell was
   ported from) -- structure lives here since .left-panel is fully shared, but the stroke
   color is brand-specific, so each including page's own <style> block supplies its own
   background-image on this same .left-panel selector (a data-URI SVG can't read a CSS var
   for its internal stroke attribute, so this can't be one shared image the way everything
   else in this file is; the 0.14 fade is baked into each SVG's stroke-opacity instead of a
   CSS opacity, since a plain background-image on the real element can't be dimmed without
   dimming its content too). See exec/build-page.js and vow/build-page.js for their own
   colored copy.
   First attempt (2026-08-27) put this pattern on an absolutely-positioned .left-panel::before
   with an explicit height:6000px, meant to outrun any realistic accordion length so the
   tiling wouldn't run out. That inverted the bug: .left-panel's overflow-y:auto scrollHeight
   is driven by its tallest child, and a 6000px pseudo-element IS a child, so it forced the
   panel to scroll 6000px deep even with the accordion fully collapsed (~756px of real
   content) -- Blake: "scroll down goes WAY beyond the builder." background-attachment:local
   is the built-in fix: it paints straight on the real scrolling element, tiles and scrolls
   with its actual content, and needs no explicit height at all -- it can never be taller or
   shorter than the content it's behind. */
.left-panel::-webkit-scrollbar{width:5px}
.left-panel::-webkit-scrollbar-track{background:transparent}
.left-panel::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}

/* RESIZER: a thin drag handle between the two panels. Desktop only -- mobile stacks the
   panels vertically, where a horizontal width has no meaning. Keyboard-operable (arrow
   keys) so this isn't a mouse-only accessibility dead end, same reasoning Blake gave for
   wanting the adjuster in the first place. */
.bshell-resizer{
  width:6px;flex-shrink:0;cursor:col-resize;position:relative;background:transparent;
  touch-action:none;
}
.bshell-resizer::after{
  content:"";position:absolute;top:0;bottom:0;left:2px;width:2px;background:var(--border);
  transition:background .15s;
}
.bshell-resizer:hover::after,.bshell-resizer.dragging::after{background:var(--accent)}
.bshell-resizer:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* RIGHT PANEL: live preview + generate controls, always visible (not just post-generate). */
.right-panel{
  flex:1;
  display:flex;
  flex-direction:column;
  /* overflow:hidden, not auto -- 2026-08-27, matching GradBuzz/ResumeBuzz's own (separately
     built) right-panel architecture, now brought here after Blake said "make the GENERATE
     button fully visible always." The panel itself no longer scrolls; .output-wrap below is
     the ONE scrolling region, so exportRow/pptxNote/genBtn -- siblings AFTER it, still direct
     children of .right-panel -- always stay on screen regardless of how long the document is,
     the same guarantee GradBuzz/ResumeBuzz's #outputArea + .generate-wrap split already gives
     for free. Previously overflow-y:auto put the Generate button in the SAME long-scrolling
     flow as the document text, so a long Business Plan buried it at the bottom of a 5000px+
     scroll -- effectively hidden, Blake's own words. */
  overflow:hidden;
  min-width:0;
  padding:1.5rem 1.75rem 2rem;
  /* Same tint as the left panel's cards, not the plain page bg -- Blake, 2026-08-27:
     "same shade in the space around each viewer." */
  background:var(--surface2, var(--bg));
}
/* The ONE scrolling region inside .right-panel -- wraps previewEmpty/status/output so the
   controls after it (exportRow, pptxNote, genBtn) are exempt from its scroll and always
   visible. display:flex/flex-direction:column preserved so .preview-empty's own flex:1
   vertical-centering still works when the document is empty; min-height:0 is required for a
   flex child to actually shrink/scroll instead of forcing its flex-column parent taller. */
.output-wrap{
  flex:1;
  display:flex;
  flex-direction:column;
  overflow-y:auto;
  min-height:0;
}
.output-wrap::-webkit-scrollbar{width:5px}
.output-wrap::-webkit-scrollbar-track{background:transparent}
.output-wrap::-webkit-scrollbar-thumb{background:var(--border);border-radius:3px}

@media(max-width:820px){
  html,body{height:auto;overflow:visible}
  body{min-height:100%}
  .bshell-main{flex-direction:column;overflow:visible}
  .left-panel{width:100% !important;flex-shrink:1;border-right:none;border-bottom:2px solid var(--border);overflow:visible}
  .bshell-resizer{display:none}
  .right-panel{overflow:visible;min-height:50vh}
  .output-wrap{overflow:visible;min-height:0}
  .left-panel select,
  .left-panel input:not([type=radio]):not([type=checkbox]),
  .left-panel textarea,
  .left-panel button:not(.shq){min-height:44px}
}

/* FORM SECTIONS / ACCORDION (the "wiz-" prefix is the established name from ResumeBuzz's
   original build, kept for continuity across the family rather than renamed on a whim). */
.form-section{padding:1rem 1.25rem;border-bottom:1px solid var(--border)}
.section-header{
  font-family:'DM Sans',sans-serif; /* NOT 'DM Sans',monospace -- see file header note */
  font-size:0.78rem;
  font-weight:700;
  letter-spacing:0.08em;
  text-transform:uppercase;
  color:var(--warm);
  margin:0 0 0.875rem; /* explicit margin-top:0 -- it's a real <h2>, and only margin-bottom
    was ever overridden here, so the browser's default h2 top margin was pushing the text
    down inside the flex row instead of centering it (Blake: "close to hugging the bottom") */
  padding-left:0.55rem;
  border-left:2.5px solid var(--accent);
}
/* Embossed cards, ported from ResumeBuzz's proven treatment (buzzresume.com/build/) rather
   than the flatter first pass -- Blake, 2026-08-27: "make them embossed and glowing a bit,"
   then twice more the same session: "again, make these thinner, bevelled/embossed, with a
   glow effect," then the correction that settled it: "I didn't mean an outer glow on the
   buttons I meant more of a sheen." SHEEN, NOT GLOW: no blurred color-tinted halo outside
   the element (that reads as glow); a bright gradient band across the upper portion instead
   (that reads as a glossy, lit surface). Colors generalized to the accent var instead of
   ResumeBuzz's own gold/amber; --emboss-lt/--emboss-dk/--surface-hi all have brand-neutral
   fallbacks so a brand's own <style> only needs to set them to override. */
.wiz-step.form-section{
  border-bottom:none;
  margin:0.35rem 0.65rem;
  padding:0.5rem 0.7rem;
  border-radius:12px;
  border:1px solid var(--border);
  background:
    linear-gradient(180deg, var(--emboss-lt, rgba(255,255,255,0.1)), transparent 45%),
    linear-gradient(180deg, var(--surface2, var(--surface)), var(--surface));
  box-shadow:0 2px 0 rgba(0,0,0,0.3), inset 0 1px 0 var(--emboss-lt, rgba(255,255,255,0.14)), inset 0 -2px 6px var(--emboss-dk, rgba(0,0,0,0.45));
  transition:transform .18s cubic-bezier(.2,.8,.2,1), box-shadow .22s, border-color .22s, background .22s;
}
.wiz-step.form-section:first-of-type{margin-top:0.5rem}
.wiz-step.form-section:hover{
  transform:translateY(-2px); border-color:var(--accent-light, var(--accent));
  box-shadow:0 10px 22px rgba(0,0,0,0.35), inset 0 1px 0 var(--emboss-lt, rgba(255,255,255,0.08)), inset 0 -2px 6px var(--emboss-dk, rgba(0,0,0,0.3));
}
.wiz-step.open.form-section{
  border-color:var(--accent-light, var(--accent)); transform:translateY(-1px);
  box-shadow:0 12px 26px rgba(0,0,0,0.4), 0 0 0 1px var(--accent-light, var(--accent)),
    inset 0 1px 0 var(--emboss-lt, rgba(255,255,255,0.1)), inset 0 -3px 8px var(--emboss-dk, rgba(0,0,0,0.3));
}
.wiz-header{display:flex;align-items:center;gap:0.6rem;cursor:pointer;user-select:none}
.form-section > .wiz-header + .wiz-body{padding-top:0.5rem}
.wiz-header .section-header{margin-bottom:0 !important;flex:1;border-left:none;padding-left:0}
/* accent-dark, not white -- both brands on this shared file right now (BuzzExec, BuzzVow)
   are LIGHT themes (Blake, 2026-08-27), so this sits on a light card surface, not a dark
   one; white-on-white would be invisible. Revisit if a dark-themed brand syncs to this file
   later. */
.wiz-header:hover .section-header{color:var(--accent-dark, var(--accent))}
.wiz-check{
  flex-shrink:0;width:20px;height:20px;border-radius:50%;border:1.5px solid var(--border);
  display:inline-flex;align-items:center;justify-content:center;font-size:0.68rem;line-height:1;
  color:transparent;transition:all .22s;background:linear-gradient(180deg,var(--surface2, var(--surface)),var(--surface));
  box-shadow:inset 0 1px 0 var(--emboss-lt, rgba(255,255,255,0.06)), inset 0 -2px 4px var(--emboss-dk, rgba(0,0,0,0.3));
}
.wiz-step.done .wiz-check{background:linear-gradient(180deg,var(--accent-light, var(--accent)),var(--accent));border-color:var(--accent-light, var(--accent));color:#fff;box-shadow:inset 0 1px 0 rgba(255,255,255,0.5)}
.wiz-step.open .wiz-check{border-color:var(--accent-light, var(--accent));box-shadow:inset 0 1px 0 var(--emboss-lt, rgba(255,255,255,0.06))}
.wiz-chev{flex-shrink:0;color:var(--muted);transition:transform .2s;font-size:0.65rem}
.wiz-step.open .wiz-chev{transform:rotate(180deg);color:var(--accent-dark, var(--accent))}
.wiz-body{display:none;padding-top:0.3rem}
.wiz-step.open .wiz-body{display:block}
.wiz-step:not(.open) .section-header{color:var(--muted)}
.wiz-step.done:not(.open) .section-header{color:var(--ink)}

/* Shared sheen/bevel button treatment -- used by .wiz-continue here and .generate-btn in
   each brand's own <style> (the actual most-important CTA, Blake: "this is the most
   important button here"). A bright gradient band up top (sheen), a dark inset at the
   bottom (bevel), a plain neutral drop shadow for lift -- never a color-tinted outer blur. */
/* Darker base (accent -> accent-dark, was accent-light -> accent) -- Blake, 2026-08-27:
   "generate buttons slightly darker shade." The sheen highlight on top still reads as a
   lit surface; it's the base fill underneath that reads too pale/washed out at the
   original lighter range. */
.bshell-sheen-btn{
  position:relative; border:none; cursor:pointer; overflow:hidden;
  background:
    linear-gradient(180deg, rgba(255,255,255,0.35), rgba(255,255,255,0) 55%),
    linear-gradient(180deg,var(--accent, var(--accent-dark)),var(--accent-dark, var(--accent)));
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.45), inset 0 -2px 5px rgba(0,0,0,0.25), 0 4px 10px rgba(0,0,0,0.3);
  transition:transform .14s cubic-bezier(.2,.8,.2,1), box-shadow .2s, filter .2s;
}
.bshell-sheen-btn:hover{transform:translateY(-2px);filter:brightness(1.05)}
.bshell-sheen-btn:active{transform:translateY(1px) scale(.99)}

.wiz-continue{
  /* white, not var(--bg) -- that was ResumeBuzz's bright gold pattern (dark text reads fine
     on gold); BuzzExec's blue accent is darker, so dark text here was low-contrast, the
     same bug class as the dropdown/hover text fixes above. Blake, 2026-08-27: "dark text on
     dark color... still an issue from before." */
  margin-top:0.85rem;color:#fff;border-radius:11px;padding:0.55rem 1.2rem;
  font-family:'DM Sans',sans-serif;font-weight:700;font-size:0.82rem;
}

/* CUSTOM DROPDOWN ("What are we writing for you?"). Replaces native <select> so a solid
   background and a brand-colored highlight actually render -- native <select> can't take
   either reliably (confirmed transparency/legibility bug on ResumeBuzz and BuzzVow, plan
   doc Phase 4 item 3). A hidden <input type=hidden> carries the real value so every existing
   docKind-reading call site keeps working unchanged; this widget only ever writes to that
   input and dispatches 'change' on it. */
/* z-index:5, not the ambient 1 every .left-panel child gets (for the honeycomb watermark
   layering) -- .docmount and the accordion form are SIBLING direct children of #leftPanel,
   so equal z-index means DOM order wins and the form would paint over the dropdown's open
   list despite its own z-index:40, since that only wins within ITS OWN stacking context.
   Found live 2026-08-27 rendering BuzzExec's rebuilt shell: the "LINK TO A BUSINESS"
   section painted through the open dropdown list instead of the list covering it.
   Same trap caught .topcontrols (Language/Region/etc select bar) the same day, on
   BuzzVow: opening the Language dropdown painted the "LINK TO A STORY" section over
   it and the list itself rendered behind the whole form -- same fix, same reason.
   REGRESSION found immediately after, same day: giving .docmount and .topcontrols the
   SAME flat z-index:5 just moved the tie one level up -- .topcontrols comes after
   .docmount in the DOM, so it now ALWAYS won, and opening the docKind dropdown got its
   own list painted over by the Language row instead ("the what are we doing dropdown
   mixes with the language"). A fixed hierarchy between two siblings that can each have
   an open floating list can only ever privilege one of them. Fixed with :focus-within:
   opening either widget focuses one of its own options (both open() implementations in
   builder-shell.js already do this for keyboard nav), so whichever one is actually open
   gets bumped above the other, in either direction, instead of a static ranking. */
.docmount,.topcontrols{position:relative;z-index:5}
.docmount:focus-within,.topcontrols:focus-within{z-index:20}
.bshell-dd{position:relative}
/* Native checkboxes (e.g. the phonetic-guide toggle) got no brand styling at all and
   rendered as the plain OS-default box next to on-brand custom dropdowns. accent-color
   is a real, broadly supported CSS property for native checkbox/radio controls -- no
   need to build a custom widget just for this. */
.left-panel input[type=checkbox]{accent-color:var(--accent-dark, var(--accent))}
/* Bold, authoritative "what's being built" label. Blake, 2026-08-27, second pass: "keep the
   text the same size and collapse the top and bottom of the white space onto it" -- text
   back to 17px, padding trimmed further so the box hugs it with just a little room, not
   grown around bigger text. */
/* Tinted, not plain white -- Blake, 2026-08-27: "add the color tints to the 'what are we
   building' dropdown too... the colored tabs will indicate that the user has the ability to
   select something important." Same --surface2 tint as the accordion cards, signaling this
   control the same way. */
.bshell-dd-btn{
  width:100%;display:flex;align-items:center;justify-content:space-between;gap:0.5rem;
  background:var(--surface2, var(--field-bg));border:1px solid var(--field-border);border-radius:8px;
  color:var(--field-text, var(--ink));padding:7px 14px;font:inherit;font-size:17px;font-weight:700;cursor:pointer;
  text-align:left;
}
.bshell-dd-btn:hover,.bshell-dd-btn[aria-expanded="true"]{border-color:var(--accent)}
.bshell-dd-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* Sized like a normal field, not the big bold "what are we building" one -- every OTHER
   native <select> scattered through the form (Speaker Type, Story link, Occasion, Tone,
   Purpose...) upgraded to this same on-brand look. Blake, 2026-08-27: "these internal
   dropdowns look default to the browser? can we make them brand colored like the other
   dropdowns?" */
.bshell-dd-btn-inline{
  padding:0.45rem 0.65rem;font-size:0.82rem;font-weight:400;border-radius:5px;
  border-color:var(--field-border);
}
.bshell-dd-chev{flex-shrink:0;color:var(--muted);transition:transform .15s;font-size:0.7rem}
.bshell-dd-btn[aria-expanded="true"] .bshell-dd-chev{transform:rotate(180deg)}
.bshell-dd-list{
  position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:40;
  background:var(--surface2, var(--surface));border:1.5px solid var(--field-border);
  border-radius:10px;padding:0.35rem;max-height:min(360px,60vh);overflow-y:auto;
  box-shadow:0 12px 32px rgba(0,0,0,0.4);
  /* Stop scroll chaining -- 2026-08-27, Blake: scrolling past the last option was
     handing the scroll off to whatever sits behind the list (the left panel, or the
     page). overscroll-behavior:contain keeps the scroll gesture inside this list once
     it hits either end, instead of leaking into the parent. */
  overscroll-behavior:contain;
}
.bshell-dd-opt{
  padding:8px 10px;border-radius:6px;font-size:14px;color:var(--ink);cursor:pointer;
}
.bshell-dd-opt:hover,.bshell-dd-opt[aria-selected="true"]{background:var(--accent);color:#fff}
.bshell-dd-opt:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
/* A real <option disabled> (tier-locked choices, e.g. ResumeBuzz's free-tier doc types)
   stays visibly present but unselectable through this custom UI too -- 2026-08-27. */
.bshell-dd-opt.bshell-dd-opt-disabled{
  cursor:not-allowed;color:var(--muted);opacity:0.55;
}
.bshell-dd-opt.bshell-dd-opt-disabled:hover{background:none;color:var(--muted)}
/* Bolder/darker, 2026-09-02 -- Blake: "make categories a little bolder so they are
   noticeable." Was font-weight:700 already, but --muted's low contrast made that
   invisible; --warm (same dark ink as headings) is what actually reads as bold. */
.bshell-dd-group{
  padding:0.65rem 0.75rem 0.25rem;font-size:0.72rem;font-weight:800;letter-spacing:0.08em;
  text-transform:uppercase;color:var(--warm);
}
.bshell-dd-group:not(:first-child){margin-top:0.3rem;border-top:1px solid var(--field-border);padding-top:0.6rem}
/* Searchable combobox input, 2026-08-27 -- Blake: "consistent language and country search
   across the other three brands... shame" + "fix the parity". A type-to-filter <input>
   sitting over a visually-hidden real <select>, same on-brand look as .bshell-dd-btn-inline
   (every other upgraded <select> on the page) rather than a separate visual treatment --
   the chevron is a background-image since a plain <input> has no child element to hold
   .bshell-dd-chev's own span. Dropdown list reuses .bshell-dd-list/.bshell-dd-opt/
   .bshell-dd-group verbatim (initSearchCombo below), so the rendered results look
   identical to every other themed dropdown, not a second style. */
.bshell-search-input{
  width:100%;background:var(--surface2, var(--field-bg));border:1px solid var(--field-border);
  border-radius:5px;color:var(--field-text, var(--ink));padding:0.45rem 2rem 0.45rem 0.65rem;
  font:inherit;font-size:0.82rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%2364748B'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 0.65rem center;
}
.bshell-search-input:focus{outline:none;border-color:var(--accent)}
/* Muted state, 2026-09-02 -- Blake, live: mirroring the current selection in full-strength
   ink read as a filled dropdown, not a search box ("I almost corrected you"). Applied only
   while the box is passively showing the current selection; removed the moment the user
   actually types (initSearchCombo's own 'input' listener), so real search text still reads
   at full strength -- confirmed separately correct on his own screenshot.
   input.bshell-search-input.bshell-search-input--muted (not just the class alone): measured
   live and found BuzzResume/BuzzGrad's own input[type=text]{color:var(--field-text)} rule
   (their page's own <style>, loaded AFTER this file on purpose so page rules win ties) beats
   a class-only selector on specificity, not just source order -- confirmed via a real
   computed-style check coming back full-strength black despite the class being applied. */
input.bshell-search-input.bshell-search-input--muted{color:var(--muted, var(--field-text, var(--ink)))}

/* Draft bar (Restore / Save / Clear), 2026-09-02 -- see initDraftBar in builder-shell.js.
   Real top/bottom margin so the row never hugs the nav (Blake, live screenshot: "make sure
   these buttons arent hugging the top"). One chrome family-wide, colored off each brand's
   own --accent/--accent-dark tokens (already defined by every brand's root, confirmed
   before writing this) rather than a hardcoded hex, so BuzzResume/BuzzExec/BuzzVow/BuzzGrad
   each render in their own real color with zero per-brand CSS. */
.bshell-draftbar{display:flex;align-items:center;flex-wrap:nowrap;gap:8px;margin:20px 20px 0}
/* Blake: bigger text. min-height stays a FLOOR (the WCAG 2.2 24px minimum hit-target
   size), not a cap, so the button grows to fit the larger label instead of clipping it. */
.bshell-draftbar-btn{flex:1 1 0;min-width:0;padding:4px 10px;border-radius:6px;font:inherit;font-weight:700;font-size:1rem;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-align:center;min-height:24px}
/* ONE color for all three -- Blake, live, all caps: "STOP MAKING THEM THREE DIFFERENT
   COLORS." Restore/Save/Clear are all the same brand accent fill, same hover shade,
   distinguished only by their label, never by hue. */
.bshell-draftbar-restore,
.bshell-draftbar-save,
.bshell-draftbar-clear{border:1px solid var(--accent);background:var(--accent);color:#fff}
.bshell-draftbar-restore:hover:not(:disabled),
.bshell-draftbar-save:hover:not(:disabled),
.bshell-draftbar-clear:hover{background:var(--accent-dark, var(--accent));border-color:var(--accent-dark, var(--accent))}
/* Disabled: dim the SAME on-brand accent fill, never swap to an off-brand gray palette
   (Blake: a fixed gray "doesn't go along with this brand"). This is the exact treatment
   Save's own disabled state already used without complaint -- one rule, on every
   button, same fill dimmed, never a second color system. */
.bshell-draftbar-btn:disabled{opacity:0.55;cursor:default}
/* A real draft IS there to restore -- pulse to draw the eye, per Blake's own ask.
   Never pulses while disabled (nothing to restore), and stands down for anyone who
   asked the OS/browser for reduced motion. */
@keyframes bshellDraftPulse{0%,100%{box-shadow:0 0 0 0 var(--accent-glow, rgba(0,0,0,.35))}50%{box-shadow:0 0 0 6px rgba(0,0,0,0)}}
.bshell-draftbar-restore:not(:disabled){animation:bshellDraftPulse 1.8s ease-in-out infinite}
@media(prefers-reduced-motion:reduce){.bshell-draftbar-restore:not(:disabled){animation:none}}
.bshell-draftbar-status{font-size:0.8rem;color:var(--muted);min-width:1px}
