html {
    background: linear-gradient(135deg, #eef2ff 0%, #f8fafc 100%);
    min-height: 100%;
}

body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: #1f2430;
    /* Was 1000px - .wide-card (the client dashboard) needs more room than
       that, and since it's a normal child element, its own max-width can
       never exceed whatever this allows regardless of what it's set to.
       Safe to raise globally: every other page's content is comfortably
       narrower than 1000px already (login/admin cards cap out around
       640-900px), except the landing page, which escapes this constraint
       entirely via its own full-bleed breakout, so is unaffected either way. */
    max-width: 1400px;
    margin: auto;
    padding: 20px;
    box-sizing: border-box;
    min-height: 100vh;
    /* Safety net for the landing page's full-bleed bands below (the
       100vw breakout technique can overshoot by a scrollbar's width on
       some browsers) - harmless elsewhere since every other page's
       content already fits within the viewport. */
    overflow-x: hidden;
}

/* Only the interview page grows its content to fill the viewport - the
   other pages (setup/admin forms) stay anchored at the top as before.
   height (not just the base body rule's min-height) is what actually caps
   it - min-height alone is a floor, not a ceiling, so overflowing content
   would just make the whole page taller instead of the flex children
   below shrinking to fit. overflow: hidden is the backstop: individual
   panes (the chat box, the written-answer textarea) already scroll
   internally on their own, so the page itself never needs to - this
   guarantees the bottom buttons stay on-screen even if some content
   (a long AI question, a small viewport) would otherwise overflow. */
body.interview-page {
    display: flex;
    flex-direction: column;
    height: 100vh;
    overflow: hidden;
}

body.interview-page h1 {
    margin: 0 0 10px 0;
    font-size: 1.4em;
    text-align: center;
}

/* The pre-interview instructions are long enough to exceed the viewport on
   shorter screens - body.interview-page's overflow: hidden (needed so the
   in-progress interview's bottom buttons never need scrolling) would
   otherwise clip the checkbox/Start button entirely rather than let you
   scroll to them. flex:1/min-height:0 is the same shrink-to-fit-parent
   gotcha as #chat-interface below; overflow-y:auto is what actually makes
   this screen (and only this screen) scrollable when its content is tall. */
#setup {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

/* Pre-interview instructions the candidate sees before clicking "Start
   Conversation" - reuses .setup-card's card styling (border/shadow/
   padding, shared with the login pages) but wider and left-aligned, since
   a login form's narrow centered layout doesn't suit a page of prose. The
   combined .setup-card.interview-instructions-card selector (rather than a
   bare .interview-instructions-card) is needed to beat .setup-card's own
   same-specificity margin-top regardless of source order - this pulls the
   card up closer to the title instead of using .setup-card's default gap,
   which is sized for the shorter login-page titles above it. */
.setup-card.interview-instructions-card {
    max-width: 958px;
    text-align: left;
    margin-top: 16px;
}

.interview-instructions-card h2 {
    margin: 0 0 6px 0;
    font-size: 1.4em;
}

.interview-instructions-list {
    margin: 0 0 20px 0;
    padding-left: 22px;
    line-height: 1.6;
}

.interview-instructions-list li {
    margin-bottom: 12px;
}

.interview-instructions-closing {
    font-weight: 600;
    margin-top: 20px;
    margin-bottom: 0;
}

/* Countdown shown in place of "Start Conversation" being clickable, while
   the candidate is on the instructions page ahead of their scheduled slot -
   see checkInterviewAccessWindow() in app.js. */
.start-countdown {
    display: none;
    text-align: center;
    max-width: 420px;
    margin: 0 auto 16px auto;
    font-weight: 600;
    color: #b45309;
}

/* --- Robot + candidate speaker cards, each with a live waveform that
   activates while that party is talking. Stacked as separate rows in
   .interview-left's grid (robot, then candidate directly above the
   question text) rather than side-by-side, so #robot-card/#candidate-card
   center themselves within their own grid row directly. --- */

#robot-card,
#candidate-card {
    justify-self: center;
    align-self: center;
}

.speaker-card {
    max-width: 170px;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 10px;
    border-radius: 14px;
    border: 2px solid transparent;
    transition: border-color 0.2s, box-shadow 0.2s;
}

/* The candidate's own card is sized up a bit beyond the shared
   .speaker-card default - it holds a real live video now (not just a
   waveform), so it reads better as the visually dominant side. */
.candidate-speaker-card {
    max-width: 220px;
}

/* Highlighted while that party is actively speaking - paired with the
   waveform itself animating, so it's readable even at a glance. */
.speaker-card.speaking {
    border-color: #4f46e5;
    box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.12);
}

.speaker-avatar {
    display: block;
    width: 100%;
    border-radius: 12px;
    box-shadow: 0 4px 16px rgba(15, 23, 42, 0.08);
}

.speaker-waveform {
    width: 100%;
    height: 36px;
    margin-top: 8px;
}

/* Modifier for the two waveform-only cards (candidate mic / AI speaker) -
   overrides .speaker-card's default column stacking (built for
   avatar-then-waveform) with a row, so the mic/speaker icon sits beside
   its waveform instead of above it. Also drops the inherited 170px
   max-width: that cap was sized for a bare waveform, but icon + waveform
   + padding needs ~200px, and without this override the content
   overflows and bleeds into the flex gap - unevenly, since which edge of
   the card (icon vs. canvas) faces the video differs between the two
   cards - making the video-to-mic and video-to-speaker gaps look
   unequal even though both use the same 16px gap. */
.speaker-card.waveform-card {
    flex-direction: row;
    gap: 8px;
    max-width: none;
    flex-shrink: 0;
}

.speaker-card.waveform-card .speaker-waveform {
    margin-top: 0;
    /* The icon (see .waveform-icon below) already refuses to shrink - without
       this, the canvas was the only thing in either card free to shrink under
       space pressure. Since it sits on the video-facing side of the mic card
       but the *outer* side of the speaker card (icon faces the video there
       instead), a shrinking canvas only ate into the mic-side gap, making the
       two sides of the video look asymmetric even though the underlying
       gap/padding math is identical. */
    flex-shrink: 0;
}

.waveform-icon {
    font-size: 1.3em;
    line-height: 1;
    flex-shrink: 0;
}

/* #chat-interface is toggled to display:flex by app.js once the interview
   starts - flex:1 lets it (and .interview-layout inside it) grow to fill
   whatever vertical space is left in the viewport, instead of shrink-
   wrapping to its content and leaving blank space below. */
#chat-interface {
    flex: 1;
    flex-direction: column;
    min-height: 0; /* same flexbox gotcha as .interview-left/.interview-right below - without this, its content can refuse to shrink below its natural size and push the page taller than the viewport */
}

.interview-layout {
    display: flex;
    flex: 1;
    gap: 24px;
    align-items: stretch;
    margin-top: 8px;
    min-height: 0; /* allows children to actually shrink/scroll instead of overflowing */
}

.interview-right {
    flex: 1.1;
    min-width: 0;
    min-height: 0; /* flexbox gotcha: without this, children can't grow/shrink past their content size */
}

/* interview-right now gets a slightly bigger flex share than interview-left
   (flipped from the old 1.15:0.85 split) so the written-answer pad reads a
   bit wider and the AI question pad a bit narrower. */
.interview-left {
    display: flex;
    flex-direction: column;
    flex: 0.9;
    min-width: 0;
    min-height: 0;
    width: 100%;
    text-align: center;
}

.interview-left .chat-box {
    width: 100%;
    flex: 1;
    box-sizing: border-box;
    margin-bottom: 0;
    font-size: 1.3em;
}

.interview-right {
    display: flex;
    flex-direction: column;
}

/* Candidate video + its two speaking-waveform indicators, pinned to the
   top right of the screen (interview-right is itself the right half of
   .interview-layout; align-self: flex-end pins this row to that half's
   right edge) rather than sharing interview-left with the question text.
   Sized down from its old, more prominent placement (see
   .candidate-video-frame/canvas widths below) so it reads as a compact
   corner insert instead of competing with the written-answer pad below
   it for space. */
.video-corner {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    align-self: flex-end;
    gap: 10px;
    margin-bottom: 16px;
    min-height: 0;
}

.candidate-video-frame {
    max-width: 130px;
    width: 100%;
    flex-shrink: 0;
}

.text-answer-label {
    font-weight: 600;
    font-size: 0.82em;
    color: #6b7280;
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

/* Sits between .interview-right and .text-answer-box now (needed so a
   click can force-enable a disabled textarea, which never fires its own
   click events) - flex:1/column so it still passes sizing through to the
   textarea exactly as if the wrapper weren't there. */
.text-answer-wrapper {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-height: 0;
}

.text-answer-box {
    flex: 1;
    width: 100%;
    /* A floor low enough that it never forces the page to overflow the
       viewport on a shorter screen - flex:1 still grows it to fill
       whatever's actually available whenever there's room to spare. */
    min-height: 80px;
    padding: 12px;
    font-family: "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.9em;
    line-height: 1.5;
    border: 1px solid #e2e2ea;
    border-radius: 8px;
    background: #fff;
    color: #1f2430;
    box-sizing: border-box;
    resize: vertical;
    transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}

.text-answer-box:disabled {
    background: #f3f4f6;
    color: #9ca3af;
}

.text-answer-box:focus {
    outline: none;
    border-color: #4f46e5;
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

@media (max-width: 640px) {
    .interview-layout {
        flex-direction: column;
    }
}

/* Sizing/border-radius/shadow come from .speaker-avatar (applied together
   on the same <video> element, in the candidate's speaker-card) - this
   class only adds the properties specific to it being a live video feed
   rather than a static image. */
.candidate-preview {
    aspect-ratio: 4 / 3;
    object-fit: cover;
    background: #000;
    transform: scaleX(-1); /* mirror, so it feels like looking in a mirror rather than a live broadcast */
}

.chat-box {
    border: 1px solid #ccc;
    padding: 10px;
    height: 90px;
    overflow-y: auto;
    margin-bottom: 20px;
    font-size: 1.05em;
    display: flex;
    align-items: center;
}

.user-msg { 
    color: blue; 
    text-align: right; 
    margin: 10px; 
}

.ai-msg { 
    color: green; 
    text-align: left; 
    margin: 10px; 
}

#status-bar {
    font-size: 1.2em;
    font-weight: bold;
    padding: 10px;
    text-align: center;
    background: #f0f0f0;
    margin-bottom: 20px;
    border-radius: 5px;
}

/* --- Schedule Interview (admin setup) page --- */

.setup-card {
    background: #ffffff;
    border: 1px solid #e2e2ea;
    border-radius: 16px;
    padding: 32px;
    margin: 40px auto 0 auto;
    max-width: 640px;
    box-shadow: 0 4px 24px rgba(15, 23, 42, 0.06);
}

.setup-card h1 {
    margin: 0 0 6px 0;
    font-size: 1.6em;
}

.setup-card .subtitle {
    color: #6b7280;
    margin: 0 0 28px 0;
    font-size: 0.95em;
}

/* Admin dashboard tab bar - "Manage Clients" / "Demo Requests" - each tab
   panel below (#admin-tab-clients/#admin-tab-demo-requests) is toggled via
   display:none/block in admin.html's switchAdminTab(), not re-rendered, so
   this is purely the button strip above them. */
.admin-tabs {
    display: flex;
    align-items: center;
    gap: 8px;
    border-bottom: 1px solid #e2e2ea;
    margin: -8px 0 24px 0;
    padding-bottom: 12px;
}

.admin-tab-btn {
    padding: 8px 16px;
    border: 1px solid transparent;
    background: transparent;
    border-radius: 8px;
    cursor: pointer;
    font-weight: 600;
    font-family: inherit;
    font-size: 0.95em;
    color: #6b7280;
    white-space: nowrap;
    transition: background 0.15s, color 0.15s;
}

.admin-tab-btn:hover {
    background: #f3f4f6;
}

.admin-tab-btn.active {
    background: #eef2ff;
    color: #3730a3;
}

.field {
    margin-bottom: 18px;
}

/* Two .field elements side by side (e.g. Candidate Name + Candidate Email)
   instead of stacked - each gets equal width via the child .field's own
   flex:1, and its margin-bottom collapses down to the row instead of
   doubling between them since the row itself has no vertical margin. */
.field-row {
    display: flex;
    gap: 14px;
}

.field-row .field {
    flex: 1;
    min-width: 0;
}

.field label {
    display: block;
    font-weight: 600;
    font-size: 0.82em;
    color: #6b7280;
    margin-bottom: 6px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.field label .hint {
    text-transform: none;
    font-weight: 400;
    letter-spacing: normal;
}

/* --- Interview Type (Skill Based / Job & Profile Based) --- */

.interview-type-row {
    display: flex;
    gap: 16px;
}

.radio-option {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.95em;
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    color: #1f2430;
    cursor: pointer;
}

.radio-option input[type="radio"] {
    accent-color: #4f46e5;
    width: 16px;
    height: 16px;
}

/* Same look as .radio-option, for standalone toggle checkboxes (e.g.
   "Require candidate video") that aren't part of a radio group. */
.checkbox-option {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.95em;
    font-weight: 400;
    text-transform: none;
    letter-spacing: normal;
    color: #1f2430;
    cursor: pointer;
}

.checkbox-option input[type="checkbox"] {
    accent-color: #4f46e5;
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.field input[type="file"] {
    width: 100%;
    padding: 9px 12px;
    font-size: 0.9em;
    font-family: inherit;
    border: 1px solid #e2e2ea;
    border-radius: 8px;
    background: #fff;
    color: #1f2430;
    box-sizing: border-box;
    margin-bottom: 8px;
}

.field textarea {
    width: 100%;
    padding: 10px 12px;
    font-size: 0.9em;
    font-family: inherit;
    line-height: 1.5;
    border: 1px solid #e2e2ea;
    border-radius: 8px;
    background: #fff;
    color: #1f2430;
    box-sizing: border-box;
    resize: vertical;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.field textarea:focus {
    outline: none;
    border-color: #4f46e5;
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

#profile-analysis-result {
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px dashed #e2e2ea;
}

.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="number"],
.field input[type="date"],
.field input[type="datetime-local"],
.field select {
    width: 100%;
    padding: 10px 12px;
    font-size: 1em;
    font-family: inherit;
    border: 1px solid #e2e2ea;
    border-radius: 8px;
    background: #fff;
    color: #1f2430;
    box-sizing: border-box;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.schedule-row {
    display: flex;
    gap: 10px;
}

.schedule-row input[type="date"] {
    flex: 3;
}

.schedule-row select {
    flex: 2;
}

/* Custom hour dropdown (not a native <select>) - see the comment in
   client.html for why: browsers largely ignore per-option CSS/inline
   color on a native select's open list, which is exactly what the
   green/red availability coloring needs. */
.hour-picker {
    position: relative;
    flex: 2;
}

.hour-picker-toggle {
    width: 100%;
    padding: 10px 12px;
    font-size: 1em;
    font-family: inherit;
    text-align: left;
    border: 1px solid #e2e2ea;
    border-radius: 8px;
    background: #fff;
    color: #1f2430;
    box-sizing: border-box;
    cursor: pointer;
    transition: border-color 0.15s, box-shadow 0.15s;
}

.hour-picker-toggle:focus {
    outline: none;
    border-color: #4f46e5;
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

.hour-picker-list {
    display: none;
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 240px;
    overflow-y: auto;
    background: #fff;
    border: 1px solid #e2e2ea;
    border-radius: 8px;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
    z-index: 20;
}

.hour-picker-list.open {
    display: block;
}

.hour-picker-option {
    padding: 8px 12px;
    font-size: 0.92em;
    cursor: pointer;
    color: #1f2430; /* neutral until an availability check colors it */
}

.hour-picker-option:hover:not(.disabled) {
    background: #f5f6ff;
}

.hour-picker-option.selected {
    background: #eef2ff;
    font-weight: 600;
}

.hour-picker-option.disabled {
    cursor: not-allowed;
    text-decoration: line-through;
    opacity: 0.75;
}

.field input[type="text"]:focus,
.field input[type="email"]:focus,
.field input[type="password"]:focus,
.field input[type="number"]:focus,
.field input[type="date"]:focus,
.field input[type="datetime-local"]:focus,
.field select:focus {
    outline: none;
    border-color: #4f46e5;
    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15);
}

.btn-primary {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: #4f46e5;
    color: #fff;
    border: none;
    padding: 12px 22px;
    font-size: 1em;
    font-weight: 600;
    font-family: inherit;
    border-radius: 8px;
    cursor: pointer;
    margin-top: 6px;
    box-shadow: 0 2px 6px rgba(79, 70, 229, 0.25);
    transition: background 0.15s, transform 0.05s, box-shadow 0.15s;
}

.btn-primary:hover {
    background: #4338ca;
    box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3);
}

.btn-primary:active {
    transform: scale(0.98);
    box-shadow: 0 1px 4px rgba(79, 70, 229, 0.25);
}

.btn-primary:disabled {
    background: #d1d5db;
    color: #6b7280;
    cursor: not-allowed;
    box-shadow: none;
}

.btn-primary:disabled:hover {
    background: #d1d5db;
    box-shadow: none;
}

.btn-primary:focus-visible,
.btn-secondary:focus-visible {
    outline: 2px solid #4f46e5;
    outline-offset: 2px;
}

#link-container:not(:empty) {
    margin-top: 20px;
}

.link-result {
    padding: 16px;
    background: #f0fdf4;
    border: 1px solid #bbf7d0;
    border-radius: 10px;
}

.link-result.error {
    background: #fef2f2;
    border-color: #fecaca;
}

.link-result .label {
    font-weight: 600;
    margin: 0 0 10px 0;
    color: #166534;
}

.link-result.error .label {
    color: #b91c1c;
    margin: 0;
}

.link-row {
    display: flex;
    gap: 8px;
}

.link-row input {
    flex: 1;
    min-width: 0;
    padding: 10px 12px;
    border: 1px solid #e2e2ea;
    border-radius: 8px;
    background: #fff;
    font-family: "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.85em;
    box-sizing: border-box;
}

.btn-secondary {
    padding: 10px 14px;
    border: 1px solid #e2e2ea;
    background: #fff;
    border-radius: 8px;
    cursor: pointer;
    font-weight: 600;
    font-family: inherit;
    white-space: nowrap;
    transition: background 0.15s;
}

.btn-secondary:hover {
    background: #f3f4f6;
}

.btn-secondary:disabled {
    cursor: not-allowed;
    opacity: 0.5;
}

.btn-secondary:disabled:hover {
    background: #fff;
}

.copy-status {
    color: #16a34a;
    margin-top: 8px;
    font-size: 0.85em;
    height: 1em;
}

.copy-status.error {
    color: #dc2626;
}

/* --- Admin: registered clients table --- */

/* Wider than the base .setup-card (640px) - the clients table has 6
   columns including inline-editable number/datetime inputs, which don't
   comfortably fit at the default width; without this the table (or its
   Edit column specifically) rendered wider than the card and spilled
   outside it instead of wrapping/scrolling within it. */
#admin-dashboard-section {
    max-width: 900px;
}

/* Safety net on top of the wider card above - if the table is ever still
   wider than available space (a narrower viewport, a long client name),
   this scrolls horizontally *within* the card instead of overflowing its
   bounds. */
#clients-table-container {
    overflow-x: auto;
}

.clients-table,
.sessions-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9em;
}

/* Inline-editable cells (see renderClientsTable() in admin.html) - fixed,
   modest widths so a row being edited doesn't balloon each cell to the
   browser's default (fairly wide) number/datetime-local input size. */
.clients-table input[type="number"] {
    width: 70px;
}

.clients-table input[type="datetime-local"] {
    width: 190px;
}

.clients-table th,
.clients-table td {
    text-align: left;
    padding: 10px 12px;
    border-bottom: 1px solid #e2e2ea;
}

/* Roomier than .clients-table's - matches the Tailwind-styled dashboard
   card's px-6/py-4 rhythm now that this table sits inside one. */
.sessions-table th,
.sessions-table td {
    text-align: left;
    padding: 16px 24px;
    border-bottom: 1px solid #e2e2ea;
}

.sessions-table tbody tr:last-child td {
    border-bottom: none;
}

.clients-table th,
.sessions-table th {
    color: #6b7280;
    font-size: 0.82em;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    font-weight: 600;
    white-space: nowrap;
}

.sessions-table td {
    vertical-align: top;
    white-space: nowrap;
}

/* --- Client app shell: tabbed Dashboard / Schedule Interview --- */

.app-nav {
    display: flex;
    justify-content: space-between;
    align-items: center;
    max-width: 1100px;
    margin: 40px auto 16px auto;
}

.tab-buttons {
    display: flex;
    gap: 8px;
}

.app-nav-account {
    display: flex;
    align-items: center;
    gap: 14px;
}

.client-welcome {
    font-weight: 600;
    color: #374151;
    font-size: 0.95em;
}

.tab-btn {
    padding: 10px 18px;
    border: 1px solid #e2e2ea;
    background: #fff;
    border-radius: 8px;
    cursor: pointer;
    font-weight: 600;
    font-family: inherit;
    font-size: 0.95em;
    color: #6b7280;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.tab-btn:hover {
    background: #f5f6ff;
}

.tab-btn.active {
    background: #4f46e5;
    border-color: #4f46e5;
    color: #fff;
}

.wide-card {
    max-width: 1360px;
}

.dashboard-header {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    align-items: flex-start;
    gap: 16px;
    margin-bottom: 18px;
}

.dashboard-header h1 {
    margin: 0 0 6px 0;
}

.dashboard-header .subtitle {
    margin: 0;
}

.dashboard-header-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 14px;
    /* Without this, the two filter dropdowns + Refresh button (a single
       nowrap row by default) could overflow past the card's right edge
       on a narrower viewport instead of wrapping - which is exactly what
       pushed Refresh outside the visible layout. Wrapping keeps the whole
       group right-aligned as a block, so Refresh stays anchored top-right
       either way, on one line or two. */
    flex-wrap: wrap;
}

.dashboard-filter-group {
    display: flex;
    align-items: center;
    gap: 8px;
}

.dashboard-filter-group label {
    font-weight: 600;
    font-size: 0.85em;
    white-space: nowrap;
}

.dashboard-filter-group select {
    padding: 8px 10px;
    border: 1px solid #e2e2ea;
    border-radius: 8px;
    font-family: inherit;
    font-size: 0.88em;
    background: #fff;
    color: #1f2430;
}

.table-scroll {
    overflow-x: auto;
}

/* Read-only account-quota summary at the top of the client dashboard (see
   loadQuotaSummary() in client.html) - same three fields the admin page's
   clients table shows for this account, just presented as stat tiles
   rather than a table row. */
.client-quota-summary {
    display: flex;
    gap: 12px;
    margin: 20px 0;
    flex-wrap: wrap;
}

.quota-stat {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 14px 20px;
    background: #f8fafc;
    border: 1px solid #e2e2ea;
    border-radius: 10px;
    min-width: 120px;
}

.quota-stat-value {
    font-size: 1.6em;
    font-weight: 700;
    color: #4f46e5;
}

.quota-stat-label {
    font-size: 0.78em;
    font-weight: 600;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.mono-cell {
    font-family: "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.85em;
    color: #4b5563;
}

.mono-cell-text {
    color: #4b5563;
}

/* Candidate and Scheduled columns: both stack a couple of short lines plus
   a button or two (Copy Link; Cancel/Reschedule), so they need to wrap
   rather than force the row wide. Scoped as .sessions-table td.wrap-cell for
   the same specificity reason as .topic-cell below - a bare class selector
   loses to .sessions-table td's white-space: nowrap. */
.sessions-table td.wrap-cell {
    max-width: 260px;
    white-space: normal;
}

/* Timing column specifically needs more room than the 260px above - each
   line there is a label plus a full formatted date ("Start time: Sep 7,
   2026, 12:15 PM UTC"), meaningfully longer than Candidate/Scheduled's own
   content, and was wrapping the date itself onto a second line mid-value.
   min-width, not max-width: the table's own layout algorithm sizes each
   column based on the table's overall available width, which was already
   rendering this column narrower than 260px - raising a max-width ceiling
   that was never actually being hit did nothing. min-width is what
   actually forces the column wider, overriding that auto-sizing. Combined
   with .wrap-cell (not a standalone override) so this reliably wins on
   specificity regardless of source order, rather than depending on which
   of the two same-specificity rules happens to appear later. */
.sessions-table td.wrap-cell.timing-cell {
    min-width: 340px;
}

.subtopics-hint {
    color: #6b7280;
    font-weight: 400;
}

/* Scoped as .sessions-table td.topic-cell (not just .topic-cell) so this
   actually outranks .sessions-table td's white-space: nowrap - a bare class
   selector has lower specificity than a class+element selector and would
   silently lose despite appearing later in the file. */
.sessions-table td.topic-cell {
    max-width: 280px;
    white-space: normal;
}

.empty-row {
    text-align: center;
    color: #6b7280;
    padding: 24px 12px;
    white-space: normal;
}

.btn-link {
    background: none;
    border: none;
    color: #4f46e5;
    font-weight: 600;
    font-family: inherit;
    font-size: 0.9em;
    cursor: pointer;
    padding: 0;
}

.btn-link:hover {
    text-decoration: underline;
}

/* Sits inside .mono-cell (the "Scheduled For" cell) below the timestamp -
   overrides the inherited monospace font so it reads as an action, not
   more schedule data, and uses red to signal it's destructive. */
.btn-link-danger {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    color: #dc2626;
    margin-top: 2px;
}

.status-pill {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 0.8em;
    font-weight: 600;
    white-space: nowrap;
}

.status-pill.status-completed {
    background: #f0fdf4;
    color: #166534;
}

.status-pill.status-progress {
    background: #eff6ff;
    color: #1d4ed8;
}

/* An interview whose own duration has elapsed (interview_started_at +
   duration_minutes) with nothing ever marking it finished - almost always
   an abandoned browser tab. Distinct from status-expired (the access
   window itself running out), which is a different, later deadline. */
.status-pill.status-incomplete {
    background: #fff7ed;
    color: #c2410c;
}

.status-pill.status-pending {
    background: #fefce8;
    color: #854d0e;
}

.status-pill.status-expired {
    background: #fef2f2;
    color: #b91c1c;
}

.status-pill.status-expired-neutral {
    background: #f3f4f6;
    color: #6b7280;
}

.status-pill.status-cancelled {
    background: #f1f5f9;
    color: #475569;
}

/* Ended early by the AI itself over suspicious activity (prompt injection,
   requests for outside help, or overwhelmingly non-genuine answers - see
   SUSPICIOUS_ACTIVITY_MARKER in llm_engine.py), not by the candidate's own
   Quit Interview click - a stronger, more alarming red than status-expired
   so it stands out as something worth a closer look. */
.status-pill.status-flagged {
    background: #fee2e2;
    color: #991b1b;
}

/* AI-detection badges (see ai_detection.py) reuse the same pill shape as
   the status column, as a clickable <button> instead of a <span> so it can
   open the detail modal. */
button.status-pill {
    border: none;
    cursor: pointer;
    font-family: inherit;
}

.status-pill.ai-label-ai {
    background: #fef2f2;
    color: #b91c1c;
}

.status-pill.ai-label-uncertain {
    background: #fffbeb;
    color: #92400e;
}

.status-pill.ai-label-human {
    background: #f0fdf4;
    color: #166534;
}

.status-pill.ai-label-insufficient {
    background: #f3f4f6;
    color: #6b7280;
}

/* --- Dashboard: shared modal for Video/History --- */

.modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(15, 23, 42, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 2000;
    padding: 20px;
    box-sizing: border-box;
}

.modal-box {
    position: relative;
    background: #fff;
    border-radius: 16px;
    padding: 28px;
    max-width: 720px;
    width: 100%;
    max-height: 85vh;
    overflow-y: auto;
    box-shadow: 0 12px 48px rgba(15, 23, 42, 0.25);
}

.modal-box h2 {
    margin: 0 0 16px 0;
    font-size: 1.2em;
    padding-right: 24px;
}

.modal-close {
    position: absolute;
    top: 18px;
    right: 18px;
    background: none;
    border: none;
    font-size: 1.1em;
    cursor: pointer;
    color: #6b7280;
    line-height: 1;
}

.modal-close:hover {
    color: #1f2430;
}

.modal-video {
    width: 100%;
    border-radius: 10px;
    background: #000;
}

.transcript-scroll {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.transcript-turn {
    padding: 10px 14px;
    border-radius: 10px;
    border: 1px solid #e2e2ea;
}

.transcript-turn p {
    margin: 4px 0 0 0;
    white-space: pre-wrap;
}

.transcript-turn.assistant {
    background: #f0fdf4;
}

.transcript-turn.user {
    background: #eff6ff;
}

.transcript-role {
    font-size: 0.72em;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: #6b7280;
}

/* --- Client landing page (pre-login marketing content) ---
   Every selector here is prefixed "landing-" (or scoped under a
   "landing-" ancestor) specifically so none of it collides with the
   shared .btn-primary/.btn-secondary/.container-style rules used
   elsewhere on this same page (dashboard, schedule form) once logged in -
   this design's source used those exact bare class names with different
   colors, which would otherwise silently override the app-wide button
   styling everywhere else on the page, not just here. body's own
   font-family/background (see the top of this file) are intentionally
   left as the page default; Inter (linked in client.html's <head>) is
   applied only within .landing-nav's containing section below. */

#client-login-section {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

.landing-container {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0 20px;
}

.landing-btn-primary {
    background-color: #4f46e5;
    color: #fff;
    padding: 12px 24px;
    border-radius: 8px;
    font-weight: 600;
    display: inline-block;
    transition: background-color 0.2s ease;
}

.landing-btn-primary:hover {
    background-color: #4338ca;
}

.landing-btn-secondary {
    background-color: transparent;
    color: #4f46e5;
    padding: 12px 24px;
    border-radius: 8px;
    font-weight: 600;
    border: 2px solid #4f46e5;
    display: inline-block;
    transition: all 0.2s ease;
}

.landing-btn-secondary:hover {
    background-color: #4f46e5;
    color: #fff;
}

.landing-section-title {
    text-align: center;
    font-size: 2.2em;
    margin-bottom: 10px;
    color: #111827;
}

.landing-section-subtitle {
    text-align: center;
    font-size: 1.05em;
    color: #6b7280;
    margin-bottom: 44px;
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
}

/* Full-bleed breakout for every band section's own background - without
   this, each would be boxed inside body's max-width: 1000px (needed
   elsewhere on this same page, for the app-shell/dashboard once logged
   in) instead of spanning the full viewport the way this design intends.
   Standard technique: 100vw + negative margins computed against the
   *viewport*, not the constrained body, pulls each section's edges out
   to the true window edges regardless of body's own max-width/padding.
   .landing-container (inside each of these) is what re-centers the
   actual content to a readable width again. */
.landing-nav,
.landing-hero,
.landing-features,
.landing-footer {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    box-sizing: border-box;
}

/* --- Nav --- */

.landing-nav {
    background-color: #fff;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
    position: sticky;
    top: 0;
    z-index: 100;
}

.landing-nav-container {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 18px 20px;
    max-width: 1100px;
    margin: 0 auto;
}

.landing-logo {
    font-size: 1.3em;
    font-weight: 700;
    color: #4f46e5;
}

.landing-nav-links {
    display: flex;
    gap: 24px;
}

.landing-nav-links a {
    font-weight: 600;
    color: #4b5563;
    text-decoration: none;
}

.landing-nav-links a:hover {
    color: #4f46e5;
}

.landing-nav-cta {
    padding: 8px 18px;
}

/* --- Hero --- */

/* The other landing bands (nav/features/footer) all have their own opaque
   full-bleed backgrounds, so a page-level background image would never
   actually be visible behind them - the hero is the only section where
   it can show through, and it's also the most natural fit thematically.
   The white overlay gradient (not the raw photo alone) is what keeps the
   headline/subhead/buttons on top legible - the source image is a busy,
   detailed office scene, not something plain enough to put text directly
   over. interview_bg.webp is a compressed copy of interview_bg.png
   (7.7MB -> ~95KB) made specifically for this - the original PNG is left
   untouched in case a different crop/version is needed later. */
.landing-hero {
    text-align: center;
    padding: 90px 20px;
    background:
        linear-gradient(to bottom, rgba(255, 255, 255, 0.88), rgba(243, 244, 246, 0.93)),
        url("/static/interview_bg.webp") center / cover no-repeat;
}

/* .landing-hero .landing-hero-eyebrow (two classes), not just
   .landing-hero-eyebrow alone - this is also a <p>, so it needs to
   outrank .landing-hero p's own font-size/color/margin below, which
   would otherwise win on specificity (class+element beats a single
   class) regardless of source order. */
.landing-hero .landing-hero-eyebrow {
    font-size: 1.05em;
    font-weight: 800;
    color: #4f46e5;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    margin-bottom: 14px;
}

.landing-hero h1 {
    font-size: 3em;
    font-weight: 700;
    color: #111827;
    margin-bottom: 20px;
    line-height: 1.2;
    letter-spacing: -0.01em;
}

.landing-hero p {
    font-size: 1.2em;
    color: #4b5563;
    max-width: 680px;
    margin: 0 auto 36px;
}

.landing-hero-buttons {
    display: flex;
    gap: 14px;
    justify-content: center;
}

/* --- Features --- */

.landing-features {
    padding: 70px 0;
    background-color: #fff;
}

.landing-features-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 26px;
}

.landing-feature-card {
    background: #f9fafb;
    padding: 28px;
    border-radius: 12px;
    border: 1px solid #e5e7eb;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.landing-feature-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.06);
}

.landing-feature-icon {
    font-size: 1.8em;
    margin-bottom: 12px;
}

.landing-feature-card h3 {
    font-size: 1.15em;
    color: #111827;
    margin-bottom: 8px;
}

.landing-feature-card p {
    color: #4b5563;
    font-size: 0.92em;
}

/* --- How it works --- */

.landing-steps {
    padding: 70px 0;
}

/* Distinguishes the "Interview Pipeline" section from the AI-interview
   steps section right above it - same card/number styling (still reads as
   part of the same "how it works" family), just a tinted background so it
   doesn't blend into the previous section as more of the same steps. */
.landing-steps-alt {
    background-color: #eef2ff;
}

.landing-steps-grid {
    display: flex;
    justify-content: space-between;
    gap: 26px;
    flex-wrap: wrap;
}

.landing-step {
    flex: 1;
    min-width: 240px;
    text-align: center;
    background: #fff;
    padding: 36px 20px;
    border-radius: 12px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.03);
}

.landing-step-number {
    background-color: #4f46e5;
    color: #fff;
    width: 36px;
    height: 36px;
    line-height: 36px;
    border-radius: 50%;
    font-weight: 700;
    margin: 0 auto 18px;
}

.landing-step h3 {
    margin-bottom: 8px;
    color: #111827;
}

/* --- Login modal: reuses the shared .modal-overlay/.modal-box (see the
   base rules earlier in this file) plus the app's own .field/.btn-primary,
   so it looks and behaves like every other modal/form in the app. --- */

.login-modal-box {
    max-width: 420px;
}

/* --- Footer --- */

.landing-footer {
    background-color: #fff;
    padding: 32px 20px;
    text-align: center;
    border-top: 1px solid #e5e7eb;
    color: #6b7280;
    font-size: 0.9em;
}

@media (max-width: 768px) {
    .landing-hero h1 {
        font-size: 2.1em;
    }
    .landing-nav-links {
        display: none;
    }
    .landing-steps-grid {
        flex-direction: column;
    }
}
