/* ============================================
   ERA RAID - Game Layout Styles
   Base layout, variables, header, views
   ============================================ */

/* CSS Variables */
:root {
    /* Color Palette */
    --bg-primary: #0d0d12;
    --bg-secondary: #14141a;
    --bg-tertiary: #1a1a22;
    --bg-panel: rgba(20, 20, 26, 0.95);
    --bg-overlay: rgba(10, 10, 15, 0.95);

    --border-dark: #2a2a35;
    --border-light: #3a3a45;
    --border-accent: #ff6b35;

    --text-primary: #e8e8ec;
    --text-secondary: #9898a8;
    --text-muted: #68687a;

    --accent-red: #ff4b4b;
    --accent-orange: #ff8b4b;
    --accent-gold: #ffd700;
    --accent-green: #4bff4b;
    --accent-blue: #4b9fff;
    --accent-purple: #9b59b6;
    --accent-cyan: #00ffff;

    /* Class Colors */
    --class-tank: #4b9fff;
    --class-melee: #ff4b4b;
    --class-ranged: #4bff4b;
    --class-healer: #ffd700;
    --class-tidecaller: #7fd6ff;   /* Descent Phase A Task 9b; the dungeon's Mystic tint for class 6 */
    --class-forgewright: #ff9a4b;  /* C1 Task 20 (§9.1): GameUtils' class 5; 4.5:1 or better on a card (#14141a) and the dungeon panel (#24242f) */
    --class-soulbinder: #9fe3c0;   /* C1 Task 20 (§9.1): GameUtils' class 7; ClientClassPaletteTests pins both */
    --class-chronoblade: #c9a7ff;  /* C2 Task 16 (PC2-30): GameUtils' class 4; 4.5:1 or better on #14141a and #24242f (ClientClassPaletteTests) */
    --class-gunslinger: #e0b070;   /* C2 Task 16 (PC2-30): GameUtils' class 8; the same two surfaces */
    --class-ninja: #12a4a0;        /* C3 Task 10 (PC3-71): GameUtils' class 9, an evergreen jade: 5.98:1 on #14141a, 5.00:1 on #24242f, and ΔE00 >= 20
                                      from every class token, rarity colour, text colour and the accent (nearest the Soulbinder's, 21.9) */

    /* Rarity Colors */
    --rarity-common: #9d9d9d;
    --rarity-uncommon: #1eff00;
    --rarity-rare: #0070dd;
    --rarity-epic: #a335ee;
    --rarity-legendary: #ff8000;

    /* Spacing */
    --spacing-xs: 4px;
    --spacing-sm: 8px;
    --spacing-md: 12px;
    --spacing-lg: 16px;
    --spacing-xl: 24px;
    --spacing-xxl: 32px;

    /* Border Radius */
    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 12px;
    --radius-xl: 16px;

    /* Font Sizes */
    --font-xs: 10px;
    --font-sm: 12px;
    --font-md: 14px;
    --font-lg: 16px;
    --font-xl: 20px;
    --font-xxl: 24px;
    --font-xxxl: 32px;

    /* Header Height */
    --header-height: 50px;

    /* Transitions */
    --transition-fast: 0.15s ease;
    --transition-normal: 0.25s ease;
    --transition-slow: 0.4s ease;

    /* Z-Index Layers */
    --z-background: 0;
    --z-content: 10;
    --z-panels: 20;
    --z-header: 100;
    --z-tooltip: 200;
    --z-modal: 300;
    --z-toast: 400;
    --z-overlay: 500;
}

/* Reset & Base */
*, *::before, *::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    width: 100%;
    height: 100%;
    overflow: hidden;
    font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', sans-serif;
    font-size: 16px;
    line-height: 1.5;
    color: var(--text-primary);
    background: var(--bg-primary);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

body.game-body {
    background: linear-gradient(135deg, var(--bg-primary) 0%, #0a0a14 100%);
}

/* Scrollbar Styles */
::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

::-webkit-scrollbar-track {
    background: var(--bg-primary);
    border-radius: 3px;
}

::-webkit-scrollbar-thumb {
    background: var(--border-dark);
    border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
    background: var(--border-light);
}

/* ============================================
   GAME HEADER
   ============================================ */

.game-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--header-height);
    background: var(--bg-primary);
    border-bottom: 1px solid var(--border-dark);
    z-index: var(--z-header);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 var(--spacing-md);
}

.game-nav {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
}

.game-logo {
    font-size: var(--font-lg);
    font-weight: 700;
    color: var(--accent-orange);
    margin-right: var(--spacing-lg);
    letter-spacing: 0.5px;
}

.game-nav-link {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--bg-secondary);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-md);
    font-size: var(--font-sm);
    color: var(--text-secondary);
    text-decoration: none;
    transition: all var(--transition-fast);
}

.game-nav-link:hover {
    background: var(--bg-tertiary);
    border-color: var(--border-light);
    color: var(--text-primary);
}

.game-nav-link i {
    font-size: var(--font-md);
}

/* Wallet Indicator */
.wallet-indicator {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-sm) var(--spacing-md);
    background: var(--bg-secondary);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-md);
    font-size: var(--font-sm);
    color: var(--text-secondary);
}

.wallet-indicator .status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent-green);
    box-shadow: 0 0 6px rgba(75, 255, 75, 0.5);
}

.wallet-indicator .wallet-key {
    font-family: 'Consolas', 'Monaco', monospace;
    color: var(--accent-blue);
    font-size: 11px;
}

.wallet-indicator .logout-btn {
    background: transparent;
    border: 1px solid var(--accent-red);
    color: var(--accent-red);
    padding: var(--spacing-xs) var(--spacing-sm);
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 11px;
    transition: all var(--transition-fast);
}

.wallet-indicator .logout-btn:hover {
    background: rgba(255, 75, 75, 0.2);
}

.wallet-indicator .logout-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* ============================================
   GAME CONTAINER
   ============================================ */

.game-container {
    position: fixed;
    top: var(--header-height);
    left: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
    /* Background image set dynamically via JS */
    background-color: var(--bg-primary);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/* Dark overlay for background images */
.game-container::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.5);
    pointer-events: none;
    z-index: 1;
}

/* Effects Canvas Layer */
.effects-canvas {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 2;
    pointer-events: none;
}

/* ============================================
   VIEW SYSTEM
   ============================================ */

.game-view {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: none;
    opacity: 0;
    transition: opacity var(--transition-normal);
    z-index: 5;
}

.game-view.active {
    display: flex;
    opacity: 1;
}

.game-view.transitioning-out {
    display: flex;
    opacity: 0;
}

.game-view.transitioning-in {
    display: flex;
    opacity: 1;
}

/* ============================================
   LOADING VIEW
   ============================================ */

#view-loading {
    justify-content: center;
    align-items: center;
    z-index: var(--z-overlay);
}

.loading-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.loading-logo {
    width: 150px;
    height: 150px;
    margin-bottom: var(--spacing-xl);
    object-fit: contain;
}

.loading-title {
    font-size: 3rem;
    font-weight: 700;
    margin-bottom: var(--spacing-md);
    background: linear-gradient(90deg, var(--accent-red), var(--accent-orange));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.loading-subtitle {
    font-size: 1.2rem;
    color: var(--text-muted);
    margin-bottom: var(--spacing-xxl);
}

.loading-bar-container {
    width: 300px;
    height: 8px;
    background: var(--bg-tertiary);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.loading-bar {
    width: 0%;
    height: 100%;
    background: linear-gradient(90deg, var(--accent-red), var(--accent-orange));
    transition: width 0.3s ease;
}

.loading-text {
    margin-top: var(--spacing-md);
    font-size: var(--font-sm);
    color: var(--text-muted);
}

/* ============================================
   ERROR VIEW
   ============================================ */

#view-error {
    background: var(--bg-overlay);
    justify-content: center;
    align-items: center;
    z-index: var(--z-overlay);
}

.error-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.error-icon {
    font-size: 4rem;
    margin-bottom: var(--spacing-lg);
}

.error-message {
    font-size: 1.2rem;
    max-width: 400px;
    margin-bottom: var(--spacing-xxl);
    color: var(--text-secondary);
}

/* ============================================
   MAIN MENU VIEW
   ============================================ */

#view-mainmenu {
    justify-content: center;
    align-items: center;
    padding: var(--spacing-xl);
    /* The menu (character card + Live Raid + chat) can outgrow the viewport,
       especially on phones. The view itself must scroll: a centered flex item
       that overflows clips at BOTH edges and the top becomes unreachable. */
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

.menu-container {
    width: 100%;
    max-width: 600px;
    /* Auto margins center like justify/align but collapse to 0 when the
       content overflows, keeping the top of the menu scrollable into view. */
    margin: auto;
}

/* Character Display */
.character-display {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-xl);
}

.character-card {
    width: 100%;
    max-width: 400px;
    background: var(--bg-panel);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-lg);
    padding: var(--spacing-xl);
    text-align: center;
}

.character-avatar {
    width: 80px;
    height: 80px;
    margin: 0 auto var(--spacing-md);
    background: var(--bg-tertiary);
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    border: 3px solid var(--border-dark);
}

.character-avatar.tank { border-color: var(--class-tank); }
.character-avatar.melee { border-color: var(--class-melee); }
.character-avatar.ranged { border-color: var(--class-ranged); }
.character-avatar.healer { border-color: var(--class-healer); }
.character-avatar.tidecaller { border-color: var(--class-tidecaller); }   /* Descent Phase A Task 11c (GameUtils' 0-9 tables) */
/* C3 Task 10, the stack pass: the menu's ring for every Descent class (it was the neutral border for all but the Tidecaller) */
.character-avatar.chronoblade { border-color: var(--class-chronoblade); }
.character-avatar.forgewright { border-color: var(--class-forgewright); }
.character-avatar.soulbinder { border-color: var(--class-soulbinder); }
.character-avatar.gunslinger { border-color: var(--class-gunslinger); }
.character-avatar.ninja { border-color: var(--class-ninja); }

.character-name {
    font-size: var(--font-xl);
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: var(--spacing-xs);
}

.character-class {
    font-size: var(--font-sm);
    color: var(--text-secondary);
    margin-bottom: var(--spacing-xs);
}

.character-level {
    font-size: var(--font-sm);
    color: var(--accent-gold);
    font-weight: 600;
    margin-bottom: var(--spacing-lg);
}

.character-stats {
    display: flex;
    justify-content: center;
    gap: var(--spacing-xl);
    margin-bottom: var(--spacing-lg);
}

.stat-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-xs);
}

.stat-label {
    font-size: var(--font-xs);
    color: var(--text-muted);
    text-transform: uppercase;
}

.stat-value {
    font-size: var(--font-lg);
    font-weight: 600;
    color: var(--text-primary);
}

.xp-bar-container {
    position: relative;
    height: 20px;
    background: var(--bg-primary);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.xp-bar {
    height: 100%;
    background: linear-gradient(90deg, var(--accent-blue), var(--accent-purple));
    transition: width 0.5s ease;
}

.xp-text {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: var(--font-xs);
    font-weight: 600;
    color: var(--text-primary);
    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
}

.menu-buttons {
    display: flex;
    gap: var(--spacing-md);
    justify-content: center;
}

/* Character Creation */
.character-creation {
    text-align: center;
}

.creation-title {
    font-size: var(--font-xxl);
    font-weight: 600;
    margin-bottom: var(--spacing-xl);
    color: var(--text-primary);
}

/* Descent Phase A Task 9b: two columns (the four classes as a 2 x 2 grid, as on phones), then the Tidecaller's card across the row */
.class-cards {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--spacing-md);
    margin-bottom: var(--spacing-xl);
}

.class-card {
    background: var(--bg-panel);
    border: 2px solid var(--border-dark);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.class-card:hover {
    border-color: var(--border-light);
    transform: translateY(-2px);
}

.class-card.selected {
    border-color: var(--accent-orange);
    box-shadow: 0 0 20px rgba(255, 139, 75, 0.3);
}

/* Descent Phase A Task 11b (9b M7): the class picker is a keyboard radio group; its focus ring is the gold one the dungeon uses, outside
   the card's own border so a chosen (orange) card still shows where focus is */
.class-card:focus { outline: none; }
.class-card:focus-visible {
    outline: 3px solid #ffd34d;
    outline-offset: 3px;
}

.class-icon {
    font-size: 2.5rem;
    margin-bottom: var(--spacing-sm);
}

.class-icon.tank { color: var(--class-tank); }
.class-icon.melee { color: var(--class-melee); }
.class-icon.ranged { color: var(--class-ranged); }
.class-icon.healer { color: var(--class-healer); }
.class-icon.tidecaller { color: var(--class-tidecaller); }

.class-name {
    font-size: var(--font-md);
    font-weight: 600;
    margin-bottom: var(--spacing-xs);
}

/* Descent Phase A Task 9b: the role line reads at 4.5:1 or better on every card (it was --text-muted, about 3.3:1) */
.class-desc {
    font-size: var(--font-xs);
    color: var(--text-secondary);
}

/* Descent Phase A Task 9b: the Tidecaller's card (design §3), a feature card across the grid's row: the icon on the left; the "New · The
   Descent" ribbon, the name, the stat line and the role beside it; the Dungeon-only caption underneath */
.class-card-descent {
    grid-column: 1 / -1;
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas:
        "icon ribbon"
        "icon name"
        "icon meta"
        "icon desc"
        "caption caption";
    column-gap: var(--spacing-lg);
    align-items: center;
    justify-items: start;
    text-align: left;
    border-color: rgba(127, 214, 255, 0.35);
}

.class-card-descent:hover {
    border-color: var(--class-tidecaller);
}

.class-card-descent.selected {
    border-color: var(--accent-orange);
}

.class-card-descent .class-icon {
    grid-area: icon;
    margin: 0 0 0 var(--spacing-sm);
}

.class-card-descent .class-name {
    grid-area: name;
    margin: 0;
}

.class-card-descent .class-desc {
    grid-area: desc;
}

.class-ribbon {
    grid-area: ribbon;
    display: inline-block;
    margin: 0 0 var(--spacing-xs);
    padding: 2px 10px;
    border-radius: 999px;
    background: rgba(127, 214, 255, 0.14);
    color: var(--class-tidecaller);
    font-size: var(--font-xs);
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
}

.class-meta {
    grid-area: meta;
    font-size: var(--font-xs);
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--class-tidecaller);
    margin: 2px 0;
}

.class-caption {
    grid-area: caption;
    justify-self: stretch;
    margin-top: var(--spacing-sm);
    padding-top: var(--spacing-sm);
    border-top: 1px solid var(--border-dark);
    font-size: var(--font-xs);
    line-height: 1.45;
    color: var(--text-secondary);
}

/* ============================================
   C1 Task 20 (§7, §9.1, PC1-26, PC1-39): the class select of six (C2 Task 16: five; C3 Task 10: six, the Ninja's card last), its detail, the
   owed-gear notice and the roster (the #character-creation prefix and !important outrank game-responsive.css's compact rules for the old
   four-card grid)
   ============================================ */

.class-select-header {
    margin: calc(-1 * var(--spacing-md)) 0 var(--spacing-lg);
    font-size: var(--font-md);
    color: var(--text-secondary);
}

#character-creation .class-cards.class-cards-c1 {
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
    gap: var(--spacing-md) !important;
    max-width: 960px;
    margin: 0 auto var(--spacing-lg) !important;
}

/* C3 Task 10 (PC3-30, PC3-70, §9.1): the layouts for six cards. The main menu's column is 600 px wide (.menu-container), too narrow for any of
   them, so while the class select shows it takes the room each layout needs. From 768 px the detail pane is RESERVED from the start beside the
   cards, its quiet placeholder until a choice (MainMenuView never hides it there), so choosing a class never moves a card: the grid's columns
   are the same before and after, and no rule here reads body.class-detail-open (the phone sheet's alone). C2's five-card bands (one row from
   1,360 px, three over two from 1,024 px) are retired with the fifth card's centring. */

/* 1,200 px and wider: the cards 3 x 2 at 232 px with 16 px gaps (728 px), a 24 px gap, the 360 px pane: 1,112 px, centred (164 px a side at
   1,440 px, where both rows and the pane sit above the fold and the name form follows below) */
@media (min-width: 1200px) {
    body.class-select-open .menu-container { max-width: 1112px; }
    #character-creation:not(.hidden) {
        display: grid;
        grid-template-columns: 728px 360px;
        column-gap: 24px;
        justify-content: center;
        align-items: start;
    }
    #character-creation .class-cards.class-cards-c1 {
        grid-template-columns: repeat(3, 232px) !important;
        gap: 16px !important;
    }
}

/* 768 to 1,199 px: C2's two-pane layout (two columns of cards, three rows, the 280 px pane beside them), the pane reserved as above. At 768 px,
   less two 16 px gutters (736 px), the pane and its 24 px gap leave 432 px: two 208 px columns with a 16 px gap */
@media (min-width: 768px) and (max-width: 1199px) {
    body.class-select-open #view-mainmenu { padding-left: 16px; padding-right: 16px; }
    body.class-select-open .menu-container { max-width: 880px; }
    #character-creation:not(.hidden) {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 280px;
        column-gap: 24px;
        align-items: start;
    }
    #character-creation .class-cards.class-cards-c1 {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
        gap: 16px !important;
    }
}

/* both bands: everything but the pane in the first column (one axis: the title, the header, the cards, the owed-gear notice and the name form;
   fix round 1, review m-1), the pane in the second beside the cards, a sidebar. The pane adds nothing to that row's height (contain: size): it
   stretches to the cards' height (never past the screen, sticky as the page scrolls) and its text scrolls inside it, so a long detail never
   pushes the notice or the name form down when a class is chosen. The notice and the form sit under the cards (browser pass, 844 x 390): the
   sticky pane travels down its own, empty column as the page scrolls and never covers the name or the Create button. Ruling PC3-B28 (fix
   round 1): the pane is an inspector driven by the choice, so it has no close control; the phone's sheet keeps its grip and its × */
@media (min-width: 768px) {
    #character-creation > .creation-title,
    #character-creation > .class-select-header,
    #character-creation > .owed-gear,
    #character-creation > .creation-form { grid-column: 1; }
    #character-creation .class-cards.class-cards-c1 {
        grid-column: 1;
        grid-row: 3;
        max-width: none;
        margin: 0 0 var(--spacing-lg) !important;
    }
    #character-creation .class-detail {
        grid-column: 2;
        grid-row: 3;
        align-self: stretch;
        contain: size;
        display: flex;
        flex-direction: column;
        position: sticky;
        top: var(--spacing-sm);
        /* pinned, it sits below the fixed header (.game-container starts at --header-height), the view's top padding (24 px at most) and its
           own 8 px, so it fits what is left of the screen with room below (browser pass, 900 x 700 and 844 x 390: 100vh alone put its last
           lines under the fold); the dynamic viewport where the browser knows it (fix round 1, m-6: iPadOS's toolbars), 100vh before */
        max-height: calc(100vh - var(--header-height) - var(--spacing-xl) - 2 * var(--spacing-sm));
        max-height: calc(100dvh - var(--header-height) - var(--spacing-xl) - 2 * var(--spacing-sm));
        max-width: none;
        margin: 0 0 var(--spacing-lg);
        padding: var(--spacing-lg) var(--spacing-sm);   /* the text's 16 px inset is 8 here and 8 in the scroller, which then has room for the title's ring */
        background: var(--bg-secondary);
    }
    /* fix round 3 (I-R2-1): the detail scrolls up and down only; nothing in it is wider than it (below), and overflow-x: hidden is the belt to
       that brace, so no wheel, trackpad or Shift+wheel can slide the text sideways */
    #character-creation .class-detail .class-detail-body:not(.hidden) {
        flex: 1 1 auto;
        min-height: 0;
        max-height: 100%;
        overflow-x: hidden;
        overflow-y: auto;
        overscroll-behavior: contain;
        padding: 0 var(--spacing-sm);
    }
    /* fix round 1 (review m-4): while more of the detail can scroll, its lower edge fades (MainMenuView sets has-more on scroll and on a choice,
       and lifts it at the end), so the builds below are cued where overlay scrollbars show nothing; not on the phone's sheet, whose Choose button
       sits at its foot */
    #character-creation .class-detail .class-detail-body.has-more {
        -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 40px), transparent);
        mask-image: linear-gradient(to bottom, #000 calc(100% - 40px), transparent);
    }
    /* the stack pass: the scroller holds no control, so Chrome and Firefox make it a Tab stop (card, scroller, name), whose arrow keys scroll the
       builds; their default ring (1 px, near black) was lost on the pane and clipped outside by the fade's mask, so its ring is the class
       select's 3 px gold, drawn inside it, and the fade lifts while it is focused. The sticky title strip (z-index 1, opaque, exactly the
       scroller's width) and its gap below paint over the ring's top, so they carry its top and side edges themselves */
    #character-creation .class-detail .class-detail-body:focus-visible { outline: 3px solid #ffd34d; outline-offset: -3px; }
    #character-creation .class-detail .class-detail-body.has-more:focus-visible { -webkit-mask-image: none; mask-image: none; }
    #character-creation .class-detail .class-detail-body:focus-visible .class-detail-title { box-shadow: inset 3px 3px 0 #ffd34d, inset -3px 0 0 #ffd34d; }
    #character-creation .class-detail .class-detail-body:focus-visible .class-detail-title::after { box-shadow: inset 3px 0 0 #ffd34d, inset -3px 0 0 #ffd34d; }
    /* C3 final fix wave (m-7, review M-S4): forced colours drop those inset shadows, so the opaque title hid the ring's top edge there; the title
       draws the ring's top and sides as its own outline in the system's text colour, and the gap strip under it stops short of the ring's sides */
    @media (forced-colors: active) {
        #character-creation .class-detail .class-detail-body:focus-visible .class-detail-title { outline: 3px solid CanvasText; outline-offset: -3px; }
        #character-creation .class-detail .class-detail-body:focus-visible .class-detail-title::after { left: 3px; right: 3px; }
    }
    /* Ruling PC3-B28 (fix round 1): no close control on the pane (display: none takes it out of the tab order: card, tick, name, Create) */
    #character-creation .class-detail .class-detail-close { display: none; }
    /* fix round 2 (N-1), bounded in fix round 3 (I-R2-1): a scrolled detail keeps its heading. The title is a sticky strip of the panel's colour
       at the scroller's top (above the text, z-index 1), exactly as wide as the scroller: its negative side margins reach into the scroller's own
       8 px padding and no further, so nothing overflows it. Plain sticky positioning: nothing moves on a choice or animates */
    #character-creation .class-detail .class-detail-title {
        position: sticky;
        top: 0;
        z-index: 1;
        margin: 0 calc(-1 * var(--spacing-sm)) var(--spacing-sm);
        padding: 0 var(--spacing-sm);
        background: var(--bg-secondary);
    }
    /* fix round 1 (m-3): the focus ring is drawn around the words only, on the title's inner span: an inset ring (the scroller would clip one
       drawn outside), the span pulled 8 px left so the words keep the text's edge, with room between the ring and the letters */
    #character-creation .class-detail .class-detail-title-text {
        display: inline-block;
        max-width: 100%;
        margin-left: calc(-1 * var(--spacing-sm));
        padding: 4px var(--spacing-sm);
    }
    /* the title's 8 px margin below it is covered too, pinned to the title's own edges (left: 0; right: 0), so the scrolled text is cut a clear
       gap under the heading; while the detail is scrolled (is-scrolled, MainMenuView.updateFade) that edge softens into a 16 px fade, the bottom
       fade's mirror, so no glyph sliver shows under the heading (at rest it covers only the empty margin) */
    #character-creation .class-detail .class-detail-title::after {
        content: '';
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        height: var(--spacing-sm);
        background: var(--bg-secondary);
    }
    #character-creation .class-detail .class-detail-body.is-scrolled .class-detail-title::after {
        height: calc(var(--spacing-sm) + 16px);
        background: linear-gradient(to bottom, var(--bg-secondary) var(--spacing-sm), transparent);
    }
    /* fix round 2 (N-2): the visible ring is an inset shadow on the words; forced-colours mode drops shadows, so the title's transparent outline
       is what that mode paints in its own focus colour */
    #character-creation .class-detail .class-detail-title:focus-visible { outline: 2px solid transparent; outline-offset: -2px; }
    #character-creation .class-detail .class-detail-title:focus-visible .class-detail-title-text { box-shadow: inset 0 0 0 3px #ffd34d; }
}

#character-creation .class-cards-c1 .class-card-descent {
    grid-column: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 2px;
    min-height: 44px;
    padding: var(--spacing-lg) !important;
    border-color: var(--border-dark);
}

#character-creation .class-cards-c1 .class-card-descent[data-key="chronoblade"]:hover { border-color: var(--class-chronoblade); }
#character-creation .class-cards-c1 .class-card-descent[data-key="gunslinger"]:hover { border-color: var(--class-gunslinger); }
#character-creation .class-cards-c1 .class-card-descent[data-key="forgewright"]:hover { border-color: var(--class-forgewright); }
#character-creation .class-cards-c1 .class-card-descent[data-key="tidecaller"]:hover { border-color: var(--class-tidecaller); }
#character-creation .class-cards-c1 .class-card-descent[data-key="soulbinder"]:hover { border-color: var(--class-soulbinder); }
#character-creation .class-cards-c1 .class-card-descent[data-key="ninja"]:hover { border-color: var(--class-ninja); }
#character-creation .class-cards-c1 .class-card-descent.selected { border-color: var(--accent-orange); }

.class-portrait {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    object-fit: cover;
    margin-bottom: var(--spacing-sm);
    background: var(--bg-tertiary);
}

#character-creation .class-cards-c1 .class-name { font-size: var(--font-lg) !important; margin: 0 !important; }
.class-card-descent[data-key="chronoblade"] .class-meta { color: var(--class-chronoblade); }
.class-card-descent[data-key="gunslinger"] .class-meta { color: var(--class-gunslinger); }
.class-card-descent[data-key="forgewright"] .class-meta { color: var(--class-forgewright); }
.class-card-descent[data-key="soulbinder"] .class-meta { color: var(--class-soulbinder); }
.class-card-descent[data-key="ninja"] .class-meta { color: var(--class-ninja); }
#character-creation .class-cards-c1 .class-desc {
    display: block !important;
    margin: var(--spacing-xs) 0 0;
    font-size: var(--font-sm);
    line-height: 1.45;
    color: var(--text-secondary);
}
#character-creation .class-cards-c1 .class-caption {
    align-self: stretch;
    font-size: var(--font-sm);
}

/* the chosen class's detail: inline under the cards (a bottom sheet on a phone, below) */
.class-detail {
    position: relative;
    max-width: 960px;
    margin: 0 auto var(--spacing-lg);
    padding: var(--spacing-lg) 56px var(--spacing-lg) var(--spacing-lg);
    background: var(--bg-panel);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    text-align: left;
    color: var(--text-primary);
}

.class-detail-close {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 44px;
    height: 44px;
    border: none;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--text-primary);
    font-size: 24px;
    line-height: 1;
    cursor: pointer;
}

.class-detail-title { font-size: var(--font-xl); margin: 0 0 var(--spacing-sm); }
.class-detail-title:focus { outline: none; }
.class-detail-title:focus-visible, .class-detail-close:focus-visible { outline: 3px solid #ffd34d; outline-offset: 2px; }
.class-fantasy, .class-resource { font-size: var(--font-md); line-height: 1.5; margin: 0 0 var(--spacing-sm); }
.class-resource { color: var(--accent-gold); }
.class-signature { font-size: var(--font-md); line-height: 1.5; margin: 0 0 var(--spacing-sm); color: var(--text-primary); font-style: italic; }
.roster-new-line { margin: var(--spacing-xs) 0 0; font-size: var(--font-sm); color: var(--accent-gold); }
.roster-new-line:empty { display: none; }
.class-builds { margin: 0; padding-left: 20px; font-size: var(--font-md); line-height: 1.5; color: var(--text-secondary); }
.class-builds strong { color: var(--text-primary); }
.class-builds li + li { margin-top: var(--spacing-xs); }

/* C3 Task 10 (PC3-70, §9.1): the reserved pane's placeholder before a choice ("Choose a class to see its builds."), quiet and centred */
.class-detail-placeholder {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 0;
    text-align: center;
    color: var(--text-secondary);
}
/* fix round 1 (review m-2): balanced lines, so the sentence never leaves "builds." alone (one line where the pane holds it) */
.class-detail-placeholder p { margin: 0; font-size: var(--font-md); line-height: 1.5; text-wrap: balance; }

/* fix round (review I2): the sheet's "Choose <class>" is the phone's (below); the desktop's inline detail keeps its layout */
#character-creation .class-detail-choose { display: none; }
.class-detail-grip { display: none; }

/* the owed-gear notice (PC1-39, PC1-P6) and its tick, a 44 px target */
.owed-gear {
    max-width: 560px;
    margin: 0 auto var(--spacing-lg);
    padding: var(--spacing-md) var(--spacing-lg);
    border: 1px solid var(--accent-gold);
    border-radius: var(--radius-md);
    background: rgba(255, 215, 0, 0.08);
    text-align: left;
    color: var(--text-primary);
    font-size: var(--font-md);
    line-height: 1.5;
}

.owed-gear p { margin: 0 0 var(--spacing-sm); }

.owed-gear-ack {
    display: inline-flex;
    align-items: center;
    gap: var(--spacing-sm);
    min-height: 44px;
    cursor: pointer;
    font-weight: 600;
}

.owed-gear-ack input { width: 22px; height: 22px; accent-color: var(--accent-orange); }
.owed-gear-ack input:focus-visible { outline: 3px solid #ffd34d; outline-offset: 2px; }

#character-creation .creation-form .btn,
#character-creation .char-name-input { min-height: 44px; }

/* the roster: a modal dialog over the whole page, the header included (it lives outside the game container) */
.roster {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    z-index: var(--z-modal);
}

.roster.hidden { display: none; }

.roster-panel {
    width: min(720px, 100%);
    max-height: 90vh;
    overflow: auto;
    background: var(--bg-primary);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-lg);
    padding: 20px;
    position: relative;
    text-align: left;
    color: var(--text-primary);
}

.roster-panel h2 { margin: 0 52px var(--spacing-md) 0; font-size: var(--font-xl); }
.roster-list { list-style: none; margin: 0 0 var(--spacing-md); padding: 0; display: grid; gap: var(--spacing-sm); }

.roster-list li {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr) auto;
    gap: 12px;
    align-items: center;
    min-height: 56px;
    padding: 8px;
    border-radius: 8px;
    border: 1px solid var(--border-dark);
    background: var(--bg-secondary);
}

.roster-list li.is-active { border-color: var(--accent-orange); }
.roster-portrait { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; background: var(--bg-tertiary); }
.roster-icon { display: flex; align-items: center; justify-content: center; font-size: 28px; }
.roster-who { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.roster-name { font-weight: 700; font-size: var(--font-lg); overflow-wrap: anywhere; }
.roster-sub { font-size: var(--font-sm); color: var(--text-secondary); }
.roster-chips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
.roster-chip { padding: 2px 8px; border-radius: 999px; font-size: var(--font-sm); font-weight: 600; border: 1px solid currentColor; }
.roster-chip-active { color: #ffb37a; }
.roster-chip-rewards { color: #ffd34d; }
.roster-chip-busy { color: #7fd6ff; }
.roster-act { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; }
.roster-reason { font-size: var(--font-sm); color: var(--text-secondary); max-width: 160px; text-align: right; }
.roster-live:empty, .roster-rewards:empty, .roster-new-reason:empty { display: none; }
.roster-live { color: #ffb37a; font-weight: 600; margin: 0 0 var(--spacing-sm); }
.roster-rewards { margin: 0 0 var(--spacing-xs); color: var(--text-primary); }
.roster-rule { margin: 0 0 var(--spacing-md); font-size: var(--font-sm); color: var(--text-secondary); line-height: 1.5; }
.roster-new-reason { margin: var(--spacing-xs) 0 0; font-size: var(--font-sm); color: var(--text-secondary); }
.roster .btn:disabled { opacity: 0.55; cursor: not-allowed; }

.roster-close {
    position: absolute;
    top: 8px;
    right: 8px;
    border: none;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--text-primary);
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
}

/* fix round (review M8): the panel holds focus while the roster loads; the rows' Enter hint is for screen readers only */
.roster-panel:focus { outline: none; }
.roster-hint {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.roster-list li:focus { outline: none; }
.roster-list li:focus-visible, .roster button:focus-visible { outline: 3px solid #ffd34d; outline-offset: 2px; }
.roster button { min-height: 44px; min-width: 44px; }

/* phone (up to 767 px): one card a row (the 64 px portrait beside the words), the detail as a bottom sheet padded by the safe areas, the roster
   full screen; MainMenuView.isSheet reads the same breakpoint */
@media (max-width: 767px) {
    #character-creation .class-cards.class-cards-c1 { grid-template-columns: 1fr !important; gap: var(--spacing-sm) !important; }
    #character-creation .class-cards-c1 .class-card-descent {
        display: grid;
        grid-template-columns: 64px minmax(0, 1fr);
        grid-template-areas: "portrait name" "portrait meta" "portrait desc" "caption caption";
        column-gap: var(--spacing-md);
        align-items: center;
        justify-items: start;
        text-align: left;
        padding: 10px 12px !important;
    }
    #character-creation .class-cards-c1 .class-portrait { grid-area: portrait; width: 64px; height: 64px; margin: 0; }
    #character-creation .class-cards-c1 .class-name { grid-area: name; }
    #character-creation .class-cards-c1 .class-meta { grid-area: meta; }
    #character-creation .class-cards-c1 .class-desc { grid-area: desc; font-size: 12px; }
    #character-creation .class-cards-c1 .class-caption { grid-area: caption; }
    .class-detail {
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        max-height: 70vh;
        /* the sheet itself no longer scrolls: its open class's text does (below), so the grip, the title and the close button stay pinned */
        overflow: hidden;
        display: flex;
        flex-direction: column;
        margin: 0;
        padding: 22px calc(56px + env(safe-area-inset-right)) 0 calc(16px + env(safe-area-inset-left));
        background: var(--bg-primary);
        border: none;
        border-top: 2px solid var(--border-light);
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        box-shadow: 0 -10px 28px rgba(0, 0, 0, 0.65);
        transform: translateY(0);
        /* opening: visible at once, so its heading can take focus in the same task; closing: hidden once the slide ends */
        transition: transform 240ms ease-out, visibility 0s;
        z-index: 40;
    }
    #character-creation .class-detail.hidden {
        display: block !important;
        transform: translateY(100%);
        visibility: hidden;
        transition: transform 240ms ease-out, visibility 0s 240ms;
    }
    /* fix round (review I2): the sheet's way forward, a full-width primary button kept in view at its bottom while the detail scrolls */
    /* the pinned header: the grip and the close button live outside the scrolling text; the title sticks to its top on the sheet's own opaque
       background, so the text scrolls cleanly under it (nothing animates: it is plain sticky positioning) */
    #character-creation .class-detail .class-detail-body:not(.hidden) {
        flex: 1 1 auto;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
    }
    #character-creation .class-detail .class-detail-title {
        position: sticky;
        top: 0;
        z-index: 1;
        margin: 0;
        padding: 0 0 var(--spacing-sm);
        background: var(--bg-primary);
    }
    #character-creation .class-detail .class-detail-title:focus-visible { outline-offset: -3px; }   /* the scroller would clip a ring drawn outside it */
    #character-creation .class-detail .class-detail-close { z-index: 2; }
    /* a decorative grab handle on the sheet's top edge */
    .class-detail-grip {
        display: block;
        position: absolute;
        top: 8px;
        left: 50%;
        width: 40px;
        height: 4px;
        margin-left: -20px;
        border-radius: 2px;
        background: var(--border-light);
    }
    /* the last bullet clears the sticky button: the list ends with room, the button masks the text scrolling under it, and it sits above the inset */
    #character-creation .class-detail .class-builds { padding-bottom: var(--spacing-lg); }
    /* the sheet has no bottom padding of its own (scrolled text would show under a button stuck above it): the body carries it, the sticky button
       holds above the safe area, and its shadows mask the text that scrolls beneath it, the inset strip included */
    #character-creation .class-detail .class-detail-body { padding-bottom: calc(10px + env(safe-area-inset-bottom)); }
    #character-creation .class-detail .class-detail-choose {
        bottom: env(safe-area-inset-bottom);
        box-shadow: 0 0 0 10px var(--bg-primary), 0 calc(10px + env(safe-area-inset-bottom)) 0 10px var(--bg-primary);
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        min-height: 44px;
        margin-top: var(--spacing-md);
        position: sticky;
    }
    .roster { padding: 0; }
    .roster-panel {
        position: fixed; inset: 0; width: 100%; max-height: none; border-radius: 0; border: none;
        padding: calc(16px + env(safe-area-inset-top)) calc(16px + env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) calc(16px + env(safe-area-inset-left));
    }
    .roster-close { top: calc(8px + env(safe-area-inset-top)); right: calc(8px + env(safe-area-inset-right)); }
    .roster-list li { grid-template-columns: 48px minmax(0, 1fr); }
    .roster-portrait { width: 48px; height: 48px; }
    .roster-act { grid-column: 1 / -1; flex-direction: row; align-items: center; justify-content: space-between; }
    .roster-act .roster-play { order: 2; margin-left: auto; }
    .roster-reason { max-width: none; text-align: left; }
}

/* phone landscape: short cards (the tagline stays on the detail); from 768 px wide they sit in the two-pane layout's two columns */
@media (max-height: 500px) and (orientation: landscape) {
    #character-creation .class-cards-c1 .class-card-descent { padding: 8px !important; }
    #character-creation .class-cards-c1 .class-portrait { width: 48px; height: 48px; margin-bottom: 4px; }
    #character-creation .class-cards-c1 .class-desc { display: none !important; }
    /* the old feature card's landscape caption (a column beside it, game-responsive.css) is a line under the name here */
    #character-creation .class-cards-c1 .class-card-descent .class-caption {
        display: block;
        margin: var(--spacing-xs) 0 0;
        padding: var(--spacing-xs) 0 0;
        border-left: none;
        border-top: 1px solid var(--border-dark);
    }
    .class-select-header { margin: 0 0 var(--spacing-sm); font-size: var(--font-sm); }
    .roster-panel { max-height: 100vh; }
}

/* reduced motion: the phone's sheet fades in place instead of sliding (C3 Task 10, §9.1: no movement, a 160 ms opacity change); the pane
   reserved from 768 px never moves at all. The OS setting first, then (fix round, review M6) the game's own (GameSettings.reducedMotion;
   MainMenuView sets the body class) */
@media (prefers-reduced-motion: reduce) and (max-width: 767px) {
    #character-creation .class-detail { transform: none; transition: opacity 160ms ease-out, visibility 0s !important; }
    #character-creation .class-detail.hidden { transform: none; opacity: 0; transition: opacity 160ms ease-out, visibility 0s 160ms !important; }
}

@media (max-width: 767px) {
    body.game-reduced-motion #character-creation .class-detail { transform: none; transition: opacity 160ms ease-out, visibility 0s !important; }
    body.game-reduced-motion #character-creation .class-detail.hidden { transform: none; opacity: 0; transition: opacity 160ms ease-out, visibility 0s 160ms !important; }
}

/* fix round 1 (review m-6): crossing the 768 px line (a turned phone or tablet) moves the detail between the pane and the sheet with no slide and
   no fade: MainMenuView sets is-instant for that change and lifts it after the next frames, so the pane never slides out as a sheet */
#character-creation .class-detail.is-instant,
#character-creation .class-detail.is-instant.hidden,
body.game-reduced-motion #character-creation .class-detail.is-instant,
body.game-reduced-motion #character-creation .class-detail.is-instant.hidden { transition: none !important; }

.creation-form {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-md);
}

.char-name-input {
    width: 100%;
    max-width: 300px;
    padding: var(--spacing-md);
    background: var(--bg-secondary);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    font-size: var(--font-md);
    text-align: center;
    transition: border-color var(--transition-fast);
}

.char-name-input:focus {
    outline: none;
    border-color: var(--accent-orange);
}

.char-name-input::placeholder {
    color: var(--text-muted);
}

/* ============================================
   MODE SELECT VIEW
   ============================================ */

#view-modeselect {
    justify-content: center;
    align-items: center;
    padding: var(--spacing-xl);
}

.mode-select-container {
    width: 100%;
    max-width: 800px;
    text-align: center;
}

.mode-title {
    font-size: var(--font-xxl);
    font-weight: 600;
    margin-bottom: var(--spacing-xl);
}

.mode-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--spacing-xl);
    margin-bottom: var(--spacing-xl);
}

.mode-card {
    background: var(--bg-panel);
    border: 2px solid var(--border-dark);
    border-radius: var(--radius-lg);
    padding: var(--spacing-xl);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.mode-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}

.mode-card.solo:hover {
    border-color: var(--accent-orange);
}

.mode-card.raid:hover {
    border-color: var(--accent-blue);
}

.mode-icon {
    font-size: 3rem;
    margin-bottom: var(--spacing-md);
}

.mode-card.solo .mode-icon { color: var(--accent-orange); }
.mode-card.raid .mode-icon { color: var(--accent-blue); }

.mode-name {
    font-size: var(--font-xl);
    font-weight: 600;
    margin-bottom: var(--spacing-sm);
}

.mode-desc {
    font-size: var(--font-sm);
    color: var(--text-secondary);
    margin-bottom: var(--spacing-lg);
}

.mode-features {
    list-style: none;
    text-align: left;
    margin-bottom: var(--spacing-lg);
}

.mode-features li {
    font-size: var(--font-sm);
    color: var(--text-muted);
    padding: var(--spacing-xs) 0;
    padding-left: var(--spacing-lg);
    position: relative;
}

.mode-features li::before {
    content: '\2713';
    position: absolute;
    left: 0;
    color: var(--accent-green);
}

/* Descent Phase B1 Task 14: "Play as", the legacy role a Descent character plays in Raid and Solo: a segmented control of 44 px targets.
   The chosen segment is filled and carries a check mark, so colour is never the only sign */
.mode-roles {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: var(--spacing-sm) var(--spacing-md);
    margin: 0 auto var(--spacing-xl);
}

.mode-roles-label {
    font-size: var(--font-sm);
    font-weight: 600;
    color: var(--text-secondary);
}

.mode-roles-options {
    display: inline-flex;
    border: 2px solid var(--border-light);
    border-radius: var(--radius-md);
    overflow: hidden;
}

.mode-role {
    min-height: 44px;
    min-width: 104px;
    padding: 0 var(--spacing-lg);
    border: 0;
    background: var(--bg-panel);
    color: var(--text-secondary);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}

.mode-role + .mode-role {
    border-left: 2px solid var(--border-light);
}

.mode-role:hover {
    color: var(--text-primary);
}

.mode-role.is-selected {
    background: var(--class-tidecaller);
    color: #0b1620;
}

.mode-role.is-selected::before {
    content: '\2713\00a0';
}

/* a light ring inside a dark one: visible on the dark segment and on the filled one */
.mode-role:focus-visible {
    outline: none;
    box-shadow: inset 0 0 0 2px #0b1620, inset 0 0 0 4px var(--text-primary);
}

.mode-role[aria-disabled="true"] {
    cursor: progress;
    opacity: 0.7;
}

/* ============================================
   CHARACTER VIEW
   ============================================ */

/* Descent Phase A Task 11c (the 9b carry): a Descent class's attributes come from its stat sheet; one line under them says so */
.attr-descent-note {
    margin: var(--spacing-sm) 0 0;
    padding-left: var(--spacing-sm);
    border-left: 2px solid var(--class-tidecaller);
    font-size: var(--font-sm);
    line-height: 1.45;
    color: var(--text-secondary);
}

#view-character {
    padding: var(--spacing-xl);
    flex-direction: column;
    overflow-y: auto;
}

.character-view-container {
    width: 100%;
    max-width: 900px;
    margin: 0 auto;
}

.character-view-header {
    display: flex;
    align-items: center;
    gap: var(--spacing-lg);
    margin-bottom: var(--spacing-xl);
}

.view-title {
    font-size: var(--font-xxl);
    font-weight: 600;
}

.character-view-tabs {
    display: flex;
    gap: var(--spacing-sm);
    margin-bottom: var(--spacing-xl);
}

.tab-btn {
    padding: var(--spacing-md) var(--spacing-xl);
    background: var(--bg-secondary);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    font-size: var(--font-md);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.tab-btn:hover {
    background: var(--bg-tertiary);
    color: var(--text-primary);
}

.tab-btn.active {
    background: var(--bg-tertiary);
    border-color: var(--accent-orange);
    color: var(--text-primary);
}

.tab-content {
    display: none;
}

.tab-content.active {
    display: block;
}

/* Stats Grid */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: var(--spacing-xl);
}

.stats-column {
    background: var(--bg-panel);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
}

.stats-title {
    font-size: var(--font-md);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: var(--spacing-md);
    padding-bottom: var(--spacing-sm);
    border-bottom: 1px solid var(--border-dark);
}

.attribute-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--spacing-sm) 0;
    gap: var(--spacing-sm);
}

.attr-name {
    color: var(--text-secondary);
    flex: 1;
}

.attr-value {
    font-weight: 600;
    color: var(--text-primary);
    min-width: 30px;
    text-align: center;
}

.attr-value .equip-bonus {
    color: var(--accent-green);
    font-weight: 500;
    font-size: 0.85em;
}

.attr-buttons {
    display: flex;
    gap: 4px;
}

.attr-btn {
    min-width: 32px;
    height: 26px;
    padding: 0 6px;
    background: var(--accent-green);
    border: none;
    border-radius: var(--radius-sm);
    color: var(--bg-primary);
    font-weight: 700;
    font-size: var(--font-xs);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.attr-btn:hover {
    transform: scale(1.05);
    filter: brightness(1.1);
}

.attr-btn:active {
    transform: scale(0.95);
}

.attr-btn.attr-all-btn {
    background: var(--accent-gold);
    color: #000;
}

.attr-btn.attr-all-btn:hover {
    background: #ffcc00;
}

.points-available {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-sm);
    margin-top: var(--spacing-md);
    padding: var(--spacing-sm) var(--spacing-md);
    background: linear-gradient(135deg, rgba(255, 193, 7, 0.15), rgba(255, 193, 7, 0.05));
    border: 1px solid rgba(255, 193, 7, 0.3);
    border-radius: var(--radius-md);
    animation: pulse-glow 2s ease-in-out infinite;
}

@keyframes pulse-glow {
    0%, 100% { box-shadow: 0 0 5px rgba(255, 193, 7, 0.2); }
    50% { box-shadow: 0 0 15px rgba(255, 193, 7, 0.4); }
}

.points-icon {
    font-size: var(--font-lg);
}

.points-label {
    color: var(--text-secondary);
    font-size: var(--font-sm);
}

.points-count {
    font-weight: 700;
    font-size: var(--font-md);
    color: var(--accent-gold);
}

/* Inventory Layout - Equipment on top, Bag below */
.inventory-layout {
    display: flex;
    flex-direction: column;
    gap: var(--spacing-lg);
}

.equipment-panel {
    background: var(--bg-panel);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    min-width: 240px;
}

.slots-title, .bag-title {
    font-size: var(--font-md);
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin-bottom: var(--spacing-md);
    text-align: center;
}

/* Character Equipment Layout */
.character-equipment {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--spacing-xs);
}

.equip-row {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: var(--spacing-sm);
}

.equip-row-head {
    margin-bottom: var(--spacing-xs);
}

.equip-row-upper {
    gap: var(--spacing-md);
}

.equip-row-middle {
    gap: var(--spacing-md);
}

.equip-row-lower {
    gap: var(--spacing-xl);
    margin-top: var(--spacing-xs);
}

/* Character Silhouette */
.character-silhouette {
    width: 50px;
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.silhouette-body {
    width: 40px;
    height: 55px;
    background: linear-gradient(180deg,
        transparent 0%,
        rgba(100, 100, 120, 0.3) 15%,
        rgba(100, 100, 120, 0.4) 50%,
        rgba(100, 100, 120, 0.3) 85%,
        transparent 100%
    );
    border-radius: 50% 50% 45% 45% / 30% 30% 60% 60%;
    position: relative;
}

.silhouette-body::before {
    content: '👤';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 1.8rem;
    opacity: 0.5;
}

/* Equipment Slot */
.equip-slot {
    width: 48px;
    height: 48px;
    background: var(--bg-secondary);
    border: 2px solid var(--border-dark);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: relative;
}

.equip-slot .slot-label {
    position: absolute;
    bottom: -14px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 8px;
    color: var(--text-muted);
    white-space: nowrap;
    opacity: 0.7;
}

.equip-slot .item-icon {
    font-size: 1.4rem;
}

.equip-slot:hover {
    border-color: var(--border-light);
    transform: scale(1.05);
}

.equip-slot.filled {
    border-color: var(--accent-blue);
    background: rgba(75, 159, 255, 0.1);
}

.equip-slot.filled .slot-label {
    display: none;
}

/* Rarity colors for equipped items */
.equip-slot.common { border-color: #9d9d9d; }
.equip-slot.uncommon { border-color: #1eff00; background: rgba(30, 255, 0, 0.1); }
.equip-slot.rare { border-color: #0070dd; background: rgba(0, 112, 221, 0.1); }
.equip-slot.epic { border-color: #a335ee; background: rgba(163, 53, 238, 0.1); }
.equip-slot.legendary { border-color: #ff8000; background: rgba(255, 128, 0, 0.15); }

.inventory-bag {
    background: var(--bg-panel);
    border: 1px solid var(--border-dark);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
}

.inventory-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
    gap: var(--spacing-sm);
}

.inventory-item {
    aspect-ratio: 1;
    background: var(--bg-secondary);
    border: 2px solid var(--border-dark);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--font-lg);
}

.inventory-item:hover {
    border-color: var(--border-light);
    transform: scale(1.05);
}

.inventory-item.common { border-color: var(--rarity-common); }
.inventory-item.uncommon { border-color: var(--rarity-uncommon); }
.inventory-item.rare { border-color: var(--rarity-rare); }
.inventory-item.epic { border-color: var(--rarity-epic); }
.inventory-item.legendary { border-color: var(--rarity-legendary); }

/* ============================================
   BUTTONS
   ============================================ */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-sm);
    padding: var(--spacing-md) var(--spacing-xl);
    font-size: var(--font-md);
    font-weight: 600;
    border: 2px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all var(--transition-fast);
    text-decoration: none;
}

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

.btn-primary {
    background: linear-gradient(135deg, var(--accent-orange), var(--accent-red));
    color: white;
}

.btn-primary:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 4px 20px rgba(255, 139, 75, 0.4);
}

.btn-secondary {
    background: var(--bg-tertiary);
    border-color: var(--border-light);
    color: var(--text-primary);
}

.btn-secondary:hover:not(:disabled) {
    border-color: var(--accent-orange);
}

.btn-danger {
    background: var(--accent-red);
    color: white;
}

.btn-success {
    background: var(--accent-green);
    color: var(--bg-primary);
}

.btn-large {
    padding: var(--spacing-lg) var(--spacing-xxl);
    font-size: var(--font-lg);
}

.btn-back {
    padding: var(--spacing-sm) var(--spacing-md);
}

/* ============================================
   UTILITY CLASSES
   ============================================ */

.hidden {
    display: none !important;
}

.visible {
    display: block !important;
}

.flex {
    display: flex !important;
}

.text-center {
    text-align: center;
}

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

/* ============================================
   PORTRAIT OVERLAY - DISABLED
   Game is fully responsive in portrait mode
   ============================================ */

.portrait-overlay {
    display: none !important;
}

/* ============================================
   TOAST NOTIFICATIONS
   ============================================ */

/* C1 final wave (final-review-client I-2): a refused join's sentence shows here on a phone, where the combat log is hidden: as wide as the
   sentence needs, never wider than the screen less a 16 px gutter each side, above the home indicator */
#toast-container {
    position: fixed;
    bottom: calc(var(--spacing-xl) + env(safe-area-inset-bottom, 0px));
    left: 50%;
    transform: translateX(-50%);
    width: max-content;
    max-width: calc(100vw - 32px);
    z-index: var(--z-toast);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-sm);
}

.game-toast {
    padding: var(--spacing-md) var(--spacing-xl);
    background: var(--bg-panel);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    font-size: var(--font-md);
    text-align: center;
    overflow-wrap: anywhere;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4);
    animation: toast-in 0.3s ease, toast-out 0.3s ease 2.7s forwards;
}

.game-toast.error {
    border-color: var(--accent-red);
    background: rgba(40, 20, 20, 0.95);
}

.game-toast.success {
    border-color: var(--accent-green);
    background: rgba(20, 40, 20, 0.95);
}

@keyframes toast-in {
    from {
        transform: translateY(20px);
        opacity: 0;
    }
    to {
        transform: translateY(0);
        opacity: 1;
    }
}

@keyframes toast-out {
    from {
        transform: translateY(0);
        opacity: 1;
    }
    to {
        transform: translateY(20px);
        opacity: 0;
    }
}

/* Login logo */
.login-logo {
    width: 120px;
    height: 120px;
    margin-bottom: var(--spacing-lg);
    object-fit: contain;
}

/* Item <-> NFT custody: an item mid-mint is frozen (spec §7.6) */
.inventory-item.minting {
    position: relative;
    opacity: 0.6;
    border-style: dashed;
}

.inventory-item.minting::after {
    content: 'MINTING';
    position: absolute;
    bottom: 2px;
    left: 0;
    right: 0;
    text-align: center;
    font-size: var(--font-xs);
    color: var(--accent-orange);
}

.item-custody-badge {
    color: var(--accent-orange);
    font-size: var(--font-sm);
}
