@import url('base.css');
@import url('buttons.css');

/* ==========================================
   Gymdooh Portal Common Styles
   Shared styles for all portal pages
   ========================================== */

/* ==========================================
   Breadcrumbs
   ========================================== */

.breadcrumbs {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 0 0 20px 0;
    font-size: var(--font-size-small, 0.875rem);
}

.breadcrumbs a {
    color: var(--primary-color);
    text-decoration: none;
    transition: color 0.2s;
}

.breadcrumbs a:hover {
    color: var(--primary-hover);
    text-decoration: underline;
}

.breadcrumbs .separator {
    color: var(--text-muted);
}

.breadcrumbs .current {
    color: var(--text-color);
}

/* ==========================================
   Page Title & Description
   ========================================== */

.page-title {
    font-size: 2rem;
    font-weight: var(--font-weight-bold, 700);
    color: var(--text-primary);
    line-height: 1.2;
    margin: 0 0 8px 0;
    background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.page-description {
    font-size: var(--font-size-body, 1rem);
    color: var(--text-secondary);
    line-height: 1.55;
    margin: 0;
}

/* ==========================================
   Table Container
   ========================================== */

.table-container {
    background: var(--dark-bg-tertiary);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 16px;
    padding: 30px;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
    margin-bottom: 30px;
}

/* ==========================================
   Overview Grid & Cards (Detail Pages)
   ========================================== */

.overview-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
}

.overview-card {
    background: var(--card-background);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 20px;
}

.overview-card h3 {
    font-size: 1.125rem;
    margin: 0 0 16px 0;
    color: var(--primary-color);
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 10px;
}

/* ==========================================
   Info Rows (Key-Value Display)
   ========================================== */

.info-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding: 10px 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.info-row:last-child {
    border-bottom: none;
}

.info-row .label {
    font-weight: 600;
    color: var(--text-muted);
    min-width: 140px;
    flex-shrink: 0;
}

.info-row .value {
    color: var(--text-color);
    text-align: right;
    word-break: break-word;
    flex: 1;
}

/* ==========================================
   Truncated ID (click to copy)
   ========================================== */

.truncated-id {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    padding: 2px 8px;
    border-radius: 4px;
    background: var(--card-background);
    border: 1px solid var(--border-color);
    transition: all 0.2s ease;
    font-family: 'Courier New', monospace;
    font-size: var(--font-size-small, 0.875rem);
}

.truncated-id:hover {
    background: var(--hover-color, rgba(34, 199, 224, 0.1));
    border-color: var(--primary-color);
}

.truncated-id .id-text {
    max-width: 120px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.truncated-id .copy-icon {
    opacity: 0.5;
    font-size: 0.75rem;
    transition: opacity 0.2s;
}

.truncated-id:hover .copy-icon {
    opacity: 1;
}

.truncated-id.copied {
    background: rgba(34, 197, 94, 0.1);
    border-color: var(--tone-positive);
}

/* Tooltip for full ID on hover */
.truncated-id[data-tooltip] {
    position: relative;
}

.truncated-id[data-tooltip]::before {
    content: attr(data-tooltip);
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    padding: 6px 10px;
    background: var(--text-color);
    color: var(--background-color);
    font-size: 0.6875rem;
    border-radius: 4px;
    white-space: nowrap;
    opacity: 0;
    visibility: hidden;
    transition: all 0.2s;
    z-index: 100;
    margin-bottom: 5px;
}

.truncated-id[data-tooltip]::after {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 50%;
    transform: translateX(-50%);
    border: 5px solid transparent;
    border-top-color: var(--text-color);
    opacity: 0;
    visibility: hidden;
    transition: all 0.2s;
}

.truncated-id[data-tooltip]:hover::before,
.truncated-id[data-tooltip]:hover::after {
    opacity: 1;
    visibility: visible;
}

/* ==========================================
   Status Badges — THE portal-wide status colour system
   ==========================================
   ONE definition, in ONE file. `.badge` used to live here AND in table.css with a
   different look (solid fill + white text vs. translucent fill + tinted text), so
   which one a page got depended on its <link> order. That is why the same value
   was green-on-white in one table and tinted-green in the next.

   Do NOT redefine .badge or .badge-* anywhere else. Do NOT hand-write a colour
   class at a call site — ask for the tone by meaning:

       GymdoohUI.statusBadge('campaign_statuses', 'paused')

   Five tones, each answering one question about the row:

     neutral    grey    Nothing to do — never started, or finished, or shelved
     positive   green   Running / released / good
     progress   cyan    In flight, waiting on somebody ELSE
     attention  amber   Waiting on YOU
     negative   red     Rejected / blocked / broken

   Values map to tones per enum category, not globally: `verified` means "checked,
   all good" on an account (positive) and "tech-checked, now awaiting content
   approval" on a content version (progress). The map lives in
   js/component-builder.js → STATUS_BADGE_CLASSES.
   ========================================== */

:root {
    /* Hue per tone. Exposed as variables so a non-badge surface that needs to agree
       with a status (a banner, a chart series, a timeline marker) can reuse them
       instead of re-picking a green. */
    --tone-neutral:   #94a3b8;
    --tone-positive:  #22c55e;
    --tone-progress:  #22c7e0;
    --tone-attention: #f59e0b;
    --tone-negative:  #ef4444;
}

.badge {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 12px;
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    line-height: 1.4;
    white-space: nowrap;
    /* The border carries the tone too, so the badge keeps its identity on the
       lighter row backgrounds (table hover, selected card) where a 15%-opacity
       fill nearly disappears. */
    border: 1px solid transparent;
}

.badge-neutral {
    background: rgba(148, 163, 184, 0.15);
    border-color: rgba(148, 163, 184, 0.35);
    color: var(--tone-neutral);
}

.badge-positive {
    background: rgba(34, 197, 94, 0.15);
    border-color: rgba(34, 197, 94, 0.35);
    color: var(--tone-positive);
}

.badge-progress {
    background: rgba(34, 199, 224, 0.15);
    border-color: rgba(34, 199, 224, 0.35);
    color: var(--tone-progress);
}

.badge-attention {
    background: rgba(245, 158, 11, 0.15);
    border-color: rgba(245, 158, 11, 0.35);
    color: var(--tone-attention);
}

.badge-negative {
    background: rgba(239, 68, 68, 0.15);
    border-color: rgba(239, 68, 68, 0.35);
    color: var(--tone-negative);
}

/* The old Bootstrap-flavoured names — badge-success / -danger / -warning / -info /
   -primary / -secondary — are GONE, not aliased. They were the mechanism by which the
   colours drifted: `badge-info` says how a thing looks, so `paused` could be filed under
   it on one page and under `badge-warning` on the next without either looking wrong. The
   five names above say what a thing MEANS, which is checkable. Every call site was
   migrated; a stray old name now renders an unstyled badge and shows up immediately. */

/* Buttons: see buttons.css (imported at top) */

/* ==========================================
   Type tags — WHAT something is, not HOW it is doing
   ==========================================
   The second half of the portal's colour language. .badge answers "how is this doing"
   with five status tones; .type-tag answers "what is this" and must never be mistaken
   for the first. Same pill and radius as .badge — but a badge carries a coloured BORDER
   and shouts in capitals, a tag has no border and is set in normal case. In a row holding
   both, the status is the one that draws the eye, which is the right way round.

   ── The role palette ──
   A colour is bound to the CONCEPT, not to the page. "Manufacturer" is the same blue as an
   account type, as an approval dimension and as an approval scope, so the colour is worth
   learning once. Before this there were three systems disagreeing about all three roles:
   Manufacturer was teal on the account pages, violet in the search bar and blue on the
   approvals page.

   The four hues sit in the blue-violet-pink arc because green / amber / red / cyan / grey
   are spoken for by the status tones. Two of the old type colours were literally status
   tones — the search bar rendered Agency in #F59E0B, the exact attention amber, and
   Operator in the brand cyan — so an agency account read as "waiting on you".

   ── Scope granularity ──
   Where a role decides at more than one level, the level takes a LIGHTER shade of the same
   hue rather than a colour of its own: a manufacturer verdict may be bound to the
   manufacturer or to one product, an operator verdict to an account or to one location.
   Hue answers "who decides", shade answers "how narrowly". Sharing a colour across
   unrelated concepts is what made the old palette unlearnable.

   NOTE: operator teal (#2dd4bf) is the nearest neighbour to the progress tone (#22c7e0).
   Chosen deliberately; if the two ever read as one in a dense row, operator is the one to
   move, not the status.
   ========================================== */

:root {
    --role-platform:     #a78bfa;   /* Gymdooh */
    --role-manufacturer: #60a5fa;
    --role-product:      #93c5fd;   /* a manufacturer verdict, narrowed to one product */
    --role-operator:     #2dd4bf;   /* Studio */
    --role-location:     #5eead4;   /* an operator verdict, narrowed to one location */
    --role-agency:       #f472b6;
}

/* Several type tags in one place (GymdoohUI.accountTypeTags). The gap belongs to the group,
   not to the tag: a margin on .type-tag would also push it away from a badge or a label it
   sits beside everywhere else it is used. */
.type-tag-group {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 6px;
    vertical-align: middle;
}

.type-tag {
    display: inline-block;
    padding: 4px 10px;
    border-radius: 12px;            /* matches .badge */
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1.4;
    white-space: nowrap;
    /* Transparent border, never coloured: it keeps the tag exactly as tall as a badge
       beside it while leaving the coloured outline as the badge's alone. */
    border: 1px solid transparent;
    /* Bare .type-tag is the classification default — an objective, a permission right, a
       product category, a support-request type. Those carry no judgement and get no hue;
       the word in the tag already says which one it is. */
    background: rgba(255, 255, 255, 0.06);
    color: var(--text-secondary);
}

.type-tag--platform     { background: rgba(167, 139, 250, 0.15); color: var(--role-platform); }
.type-tag--manufacturer { background: rgba(96, 165, 250, 0.15);  color: var(--role-manufacturer); }
.type-tag--product      { background: rgba(147, 197, 253, 0.15); color: var(--role-product); }
.type-tag--operator     { background: rgba(45, 212, 191, 0.15);  color: var(--role-operator); }
.type-tag--location     { background: rgba(94, 234, 212, 0.15);  color: var(--role-location); }
.type-tag--agency       { background: rgba(244, 114, 182, 0.15); color: var(--role-agency); }

/* An approval scope bound to a studio's account is the operator deciding at his widest —
   same hue, same meaning. The alias exists because the API calls that scope `account`. */
.type-tag--account      { background: rgba(45, 212, 191, 0.15);  color: var(--role-operator); }

/* ==========================================
   Section Titles & Descriptions (UNIFIED — DO NOT OVERRIDE PER-PAGE)
   ==========================================
   Standard markup:
     <section class="...">
       <h2 class="section-title">Title</h2>
       <p class="section-description">Optional explainer text…</p>
       …content…
     </section>

   With count / extra controls on the right:
     <div class="section-header">
       <div class="section-header-left">
         <h2 class="section-title">Locations</h2>
         <span class="section-count">12 total</span>
       </div>
       <button class="btn btn-primary">+ Create</button>
     </div>

   Heading spec (locked in portal-common — never override per-page):
     · 1.25rem / 600 weight / --text-primary
     · 3px cyan border-bottom under heading (full-width, left-flush)
     · 8px padding-bottom, 16px margin-bottom
   ========================================== */

.section-title,
section.table-container > h2,
.table-container > .section-header > h2,
.table-container > .section-header > .section-header-left > h2 {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--text-primary);
    line-height: 1.3;
    margin: 0 0 16px 0;
    padding: 0 0 8px 0;
    border-bottom: 3px solid var(--primary-color);
}

/* When a section title sits inside a .section-header flex row (with count badge
   and/or trailing button), the row itself owns the bottom spacing and we drop
   the underline so the flex row stays clean. */
.section-header .section-title,
.section-header-left .section-title,
.table-container > .section-header > h2,
.table-container > .section-header > .section-header-left > h2 {
    margin: 0;
    padding: 0;
    border-bottom: none;
}

/* Underline the whole section-header row instead, so the visual rule still
   matches the standalone .section-title. */
.section-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    margin-bottom: 16px;
    padding-bottom: 8px;
    border-bottom: 3px solid var(--primary-color);
}

.section-header-left {
    display: flex;
    align-items: center;
    gap: 16px;
}

/* The trailing side of the row when it holds more than a single button — a filter toggle
   next to the create action, for instance. */
.section-header-actions {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

.section-count {
    font-size: var(--font-size-small, 0.875rem);
    color: var(--text-muted);
    padding: 6px 12px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 4px;
}

/* Explainer paragraph that follows a section title (or appears under any
   .section-title / .section-header). Use .actions-description as an alias
   inside action sections — both share the same visual treatment. */
.section-description,
.actions-description {
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.55;
    margin: -4px 0 20px 0;
}

/* ==========================================
   Loading & Error States
   ========================================== */

.loading-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 400px;
    gap: 20px;
}

.loading-spinner {
    width: 50px;
    height: 50px;
    border: 3px solid var(--border-color);
    border-top-color: var(--primary-color);
    border-radius: 50%;
    animation: spin 1s linear infinite;   /* @keyframes spin: base.css */
}

.error-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 400px;
    gap: 20px;
    text-align: center;
}

.error-icon {
    font-size: 4rem;
}

.error-container h2 {
    color: var(--danger-color);
    margin: 0;
}

.error-container p {
    color: var(--text-muted);
    max-width: 500px;
}

/* ==========================================
   Alerts
   ========================================== */

.alert {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 20px;
    border-radius: 8px;
    font-size: var(--font-size-small, 0.875rem);
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.alert-success {
    background: rgba(40, 167, 69, 0.9);
    color: white;
}

.alert-error {
    background: rgba(220, 53, 69, 0.9);
    color: white;
}

.alert-warning {
    background: rgba(255, 193, 7, 0.9);
    color: #000;
}

.alert-info {
    background: rgba(23, 162, 184, 0.9);
    color: white;
}

.alert-icon {
    font-size: 1.25rem;
    display: inline-flex;
}

.alert-message {
    flex: 1;
}

/* ==========================================
   Toast stack
   ==========================================
   Every floating alert lands in one column at the top of the viewport. They used to be
   positioned one by one at `top: 100px`, so the second one covered the first exactly —
   two messages, one visible, and no way to move either. */

.alert-stack {
    position: fixed;
    top: 88px;               /* clear of the fixed nav */
    left: 50%;
    transform: translateX(-50%);
    z-index: 1200;
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: min(600px, calc(100vw - 32px));
    pointer-events: none;    /* the column must not swallow clicks between toasts */
}

.alert-stack .alert {
    pointer-events: auto;
    transition: opacity 0.2s ease;
}

.alert-close {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    padding: 2px;
    border: none;
    border-radius: 4px;
    background: transparent;
    color: inherit;
    opacity: 0.7;
    cursor: pointer;
}

.alert-close:hover {
    opacity: 1;
    background: rgba(0, 0, 0, 0.15);
}

@media (max-width: 640px) {
    .alert-stack {
        top: 72px;
    }
}

/* ==========================================
   Responsive Design
   ========================================== */

@media (max-width: 968px) {
    .page-title {
        font-size: 1.75rem;
    }

    .table-container {
        padding: 20px;
        margin: 0 -20px;
        border-radius: 0;
    }
}

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

    .info-row {
        flex-direction: column;
        gap: 5px;
    }

    .info-row .value {
        text-align: left;
    }

    .section-header {
        flex-direction: column;
        gap: 15px;
        align-items: flex-start;
    }
}

@media (max-width: 640px) {
    .page-title {
        font-size: var(--font-size-h3, 1.5rem);
    }

    .page-description {
        font-size: var(--font-size-small, 0.875rem);
    }

    .table-container {
        padding: 15px;
    }
}

/* ==========================================
   Approval Timeline Stepper
   ========================================== */

.approval-timeline {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: 20px 0;
}

.timeline-step {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    position: relative;
    padding-bottom: 24px;
}

.timeline-step:last-child {
    padding-bottom: 0;
}

.timeline-step:last-child .timeline-connector {
    display: none;
}

.timeline-marker {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.75rem;
    font-weight: 700;
    flex-shrink: 0;
    z-index: 1;
    border: 2px solid transparent;
}

/* Same tones as the badges — an approval timeline sits next to the badge describing the
   same decision, and the two used to disagree: the marker took --success-color (#28a745)
   while the badge took #22c55e. */
.timeline-marker.pending {
    background: rgba(245, 158, 11, 0.2);
    border-color: var(--tone-attention);
    color: var(--tone-attention);
}

.timeline-marker.approved {
    background: rgba(34, 197, 94, 0.2);
    border-color: var(--tone-positive);
    color: var(--tone-positive);
}

.timeline-marker.rejected {
    background: rgba(239, 68, 68, 0.2);
    border-color: var(--tone-negative);
    color: var(--tone-negative);
}

.timeline-connector {
    position: absolute;
    left: 15px;
    top: 32px;
    width: 2px;
    height: calc(100% - 32px);
    background: rgba(255, 255, 255, 0.1);
}

.timeline-content {
    flex: 1;
    min-width: 0;
}

.timeline-title {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--text-primary);
    margin-bottom: 4px;
}

.timeline-subtitle {
    font-size: 0.8rem;
    color: var(--text-secondary);
    margin-bottom: 4px;
}

.timeline-meta {
    font-size: 0.75rem;
    color: var(--text-muted);
}

/* ==========================================
   Bulk Actions Bar
   ========================================== */

.bulk-actions-bar {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    background: rgba(91, 203, 207, 0.1);
    border: 1px solid rgba(91, 203, 207, 0.3);
    border-radius: 10px;
    margin-bottom: 16px;
    display: none;
}

.bulk-actions-bar.visible {
    display: flex;
}

.bulk-count {
    font-size: 0.875rem;
    color: var(--text-primary);
    font-weight: 600;
    white-space: nowrap;
}

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

/* ==========================================
   Content Preview Frame
   ========================================== */

.preview-frame-container {
    position: relative;
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 10px;
    overflow: hidden;
    background: #000;
    aspect-ratio: 16/9;
    max-height: 500px;
}

.preview-frame-container iframe {
    width: 100%;
    height: 100%;
    border: none;
}

.preview-actions {
    display: flex;
    gap: 10px;
    margin-top: 12px;
}

@media (max-width: 768px) {
    .bulk-actions-bar {
        flex-direction: column;
        align-items: stretch;
    }
}

/* ==========================================
   Page Container (standard max-width wrapper)
   ========================================== */

.page-container {
    max-width: 1400px;
    margin: 0 auto;
    width: 100%;
    padding: 0 20px;
}

@media (max-width: 640px) {
    .page-container {
        padding: 0 10px;
    }
}

/* ==========================================
   Page Header Bar (list pages: title + create button)
   ========================================== */

.page-header-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 30px;
    gap: 20px;
    flex-wrap: wrap;
}

.page-header-bar .header-content {
    flex: 1;
    min-width: 250px;
}

.page-header-bar .header-actions {
    display: flex;
    gap: 12px;
}

@media (max-width: 968px) {
    .page-header-bar {
        flex-direction: column;
        align-items: flex-start;
    }

    .page-header-bar .header-actions {
        width: 100%;
    }
}

/* ==========================================
   Page Header (detail/create/delete pages)
   ========================================== */

.page-header {
    margin-bottom: 30px;
}

.page-header h1 {
    margin: 0 0 8px 0;
    font-size: 2rem;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.2;
}

.page-header .page-subtitle {
    font-size: var(--font-size-body, 1rem);
    color: var(--text-secondary);
    margin: 0;
}

/* Delete page variant */
.page-header.page-header--danger {
    text-align: center;
    margin-bottom: 2.5rem;
}

.page-header--danger .warning-icon {
    font-size: 4rem;
    margin-bottom: 1rem;
}

.page-header--danger h1 {
    color: var(--danger-color);
    font-size: 2rem;
    font-weight: 700;
    margin-bottom: 0.5rem;
}

.page-header--danger p {
    color: var(--text-secondary);
    font-size: 1rem;
}

/* ==========================================
   Loading State
   ========================================== */

.loading-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 400px;
    gap: 20px;
}

.loading-container p {
    color: var(--text-secondary);
    font-size: var(--font-size-body, 1rem);
}

.spinner {
    width: 50px;
    height: 50px;
    border: 4px solid rgba(255, 255, 255, 0.1);
    border-top-color: var(--primary-color);
    border-radius: 50%;
    animation: spin 1s linear infinite;   /* @keyframes spin: base.css */
}

/* Danger variant for delete pages */
.spinner--danger {
    border-top-color: var(--danger-color);
}

/* ==========================================
   Stacked cell
   ==========================================
   Several facts in one table cell, one per line.

   The pattern used to be `<br>` between them, and the spacing that produced was whatever the
   line box happened to be: a pill's inline-block height sets its own line, so a row of badges
   sat further from its neighbour than a row of tags did. On the accounts list that read as
   Verification and Compliance being spaced while Types was jammed against the line above it —
   nobody chose either distance. A flex column states the gap once. */

.stacked-cell {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 5px;
}

/* Each line: its caption and whatever it captions, on a shared baseline. */
.stacked-cell-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px;
    min-height: 0;
}

/* A link off this application, rendered by externalLink() in js/portal-utils.js. The colour
   was an inline style on each of the two hand-built copies this replaced. */
.external-link {
    color: var(--primary-color);
    word-break: break-all;
}

/* ==========================================
   Pager (GymdoohUI.pager)
   ==========================================
   For paged lists that are not DataTables — the approval decisions, an audit log. Reuses
   .pagination-btn from table.css so the buttons are the portal's buttons and not a third
   opinion about what a Next looks like. */

.gd-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
}

.gd-pager-info {
    font-size: 0.8rem;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.gd-pager-controls {
    display: flex;
    gap: 8px;
}

/* ==========================================
   Stats Cards
   ========================================== */

.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 20px;
    margin-bottom: 30px;
}

.stat-card-small {
    background: var(--dark-bg-tertiary);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 12px;
    padding: 20px;
    text-align: center;
    transition: var(--transition-smooth);
}

.stat-card-small:hover {
    border-color: rgba(34, 199, 224, 0.3);
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}

.stat-label {
    font-size: var(--font-size-small, 0.875rem);
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 0.5px;
    font-weight: 600;
    margin-bottom: 8px;
}

.stat-value-small {
    font-size: var(--font-size-h2, 2.25rem);
    font-weight: 700;
    background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.stat-success {
    background: linear-gradient(135deg, #22c55e, #16a34a);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.stat-warning {
    background: linear-gradient(135deg, #f59e0b, #d97706);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

/* Same hue as the progress tone. It was #3b82f6 blue while the badges below the tiles used
   cyan, so a tile counting things in review and the badges it counted did not match. */
.stat-info {
    background: linear-gradient(135deg, #22c7e0, #0e9bb0);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.stat-muted {
    background: none;
    -webkit-background-clip: unset;
    -webkit-text-fill-color: var(--text-muted);
    background-clip: unset;
}

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

/* ==========================================
   Action Buttons (detail page actions)
   ========================================== */

.action-buttons {
    display: flex;
    gap: 16px;
    flex-wrap: wrap;
}

.action-buttons button,
.action-buttons a {
    min-width: 180px;
}

.action-buttons-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
}

/* Go-To / Navigate-to-parent buttons — visually distinct from action buttons */
.goto-buttons {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 20px;
    padding-bottom: 16px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.btn-goto {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    font-size: 0.875rem;
    font-weight: 500;
    color: var(--primary-color);
    background: rgba(34, 199, 224, 0.08);
    border: 1px solid rgba(34, 199, 224, 0.25);
    border-radius: 8px;
    text-decoration: none;
    transition: var(--transition-smooth);
    cursor: pointer;
}

.btn-goto:hover {
    background: rgba(34, 199, 224, 0.15);
    border-color: var(--primary-color);
    color: var(--text-primary);
}

.btn-goto .goto-icon {
    font-size: 1rem;
}

.btn-goto .goto-arrow {
    font-size: 0.75rem;
    opacity: 0.7;
}

/* .actions-description is defined together with .section-description above
   under "Section Titles & Descriptions (UNIFIED)" — keep both selectors in
   sync so action sections and select sections look identical. */

@media (max-width: 768px) {
    .action-buttons {
        width: 100%;
        flex-direction: column;
    }

    .action-buttons button,
    .action-buttons a {
        width: 100%;
        justify-content: center;
    }
}

/* ==========================================
   Form Actions (create/edit/delete page buttons)
   ========================================== */

.form-actions {
    display: flex;
    gap: 1rem;
    justify-content: flex-end;
    margin-top: 2rem;
    padding-top: 2rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.form-actions button,
.form-actions a {
    min-width: 200px;
}

/* Pushes everything after it to the right, so a destructive action can sit on the far left
   rather than beside the button people are about to press. */
.form-actions-spacer {
    flex: 1;
}

/* A link-styled action is not one of the two big buttons and must not be sized like one. */
.form-actions .btn-link-danger {
    min-width: 0;
}

/* A destructive action left of the spacer is still a real button, so it keeps the shared
   sizing — it is simply not the one the cursor lands next to after a save. */
.form-actions .btn-danger {
    min-width: 200px;
}

@media (max-width: 768px) {
    .form-actions {
        flex-direction: column-reverse;
    }

    .form-actions button,
    .form-actions a {
        width: 100%;
    }
}

/* Approval scope tags were their own component (.scope-tag) with their own palette and a
   20px radius. They are type tags — "whose verdict is this, and how narrowly does it
   bind" — so they are .type-tag now, with the role modifiers above. The old palette put
   `account` on #fbbf24, a hair from the attention amber, so a studio-scoped verdict read
   as something overdue. */

/* ==========================================
   Activation readiness checklist
   ==========================================
   What an action needs before it will be allowed, shown before the action is attempted.
   Replaces a browser dialog that named one missing condition at a time, after the fact.
   Server-driven: every line here comes from the same evaluation the write performs. */

.readiness {
    margin: 0 0 20px;
    padding: 16px 18px;
    border: 1px solid var(--line-2);
    border-left-width: 4px;
    border-radius: 8px;
    background: var(--dark-bg-secondary);
}

.readiness--blocked { border-left-color: var(--tone-attention); }
.readiness--ready { border-left-color: var(--tone-positive); }

.readiness-heading {
    margin: 0 0 12px;
    color: var(--text-primary);
    font-size: 0.92rem;
    font-weight: 600;
}

.readiness-list {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.readiness-check {
    display: flex;
    align-items: flex-start;
    gap: 11px;
}

/* The mark repeats what the colour says — a checklist read without colour is still a
   checklist. */
.readiness-mark {
    flex: 0 0 20px;
    height: 20px;
    margin-top: 1px;
    border-radius: 50%;
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 20px;
    text-align: center;
}

/* A readiness check is a status of the thing it gates, so it takes the status tones —
   it used to carry a third green (#4caf50) and a third amber (#ffb74d) of its own. */
.readiness-check--ok .readiness-mark {
    background: rgba(34, 197, 94, 0.18);
    color: var(--tone-positive);
}

.readiness-check--todo .readiness-mark {
    background: rgba(245, 158, 11, 0.18);
    color: var(--tone-attention);
}

.readiness-body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.readiness-title {
    color: var(--text-primary);
    font-size: 0.86rem;
    font-weight: 600;
}

.readiness-detail {
    color: var(--text-secondary);
    font-size: 0.8rem;
    line-height: 1.45;
}

/* What to do about it — only present on a check that has not passed. */
.readiness-remedy {
    color: var(--text-muted);
    font-size: 0.78rem;
    line-height: 1.45;
    font-style: italic;
}

.readiness-check--ok .readiness-title {
    color: var(--text-secondary);
    font-weight: 500;
}

/* A button that will be refused. Still clickable — the server decides, not this class — but
   it should not look like the obvious next step. */
.btn-attention {
    opacity: 0.75;
    box-shadow: inset 0 0 0 1px var(--tone-attention);
}

/* ==========================================
   Environment banner (js/components.js)
   ==========================================
   Amber, not red: this is a standing condition of the machine, not an error the reader caused,
   and a red bar at the top of every page stops being read within a day. Not fixed-position
   either — it scrolls away with the rest, because it needs to be seen once per page and not
   compete with the content afterwards. */

.env-banner {
    padding: 8px 20px;
    text-align: center;
    font-size: 0.82rem;
    line-height: 1.45;
    color: #fbbf24;
    background: rgba(245, 158, 11, 0.12);
    border-bottom: 1px solid rgba(245, 158, 11, 0.4);
}

.env-banner strong {
    color: #fcd34d;
}
