/* Style de l'application, selon la charte graphique (ADR 0010, * docs/identite/charte/) : les couleurs, tailles et rayons sont les * variables de tokens.json, sous le même nom, redéfinies pour le thème * sombre ; les composants reprennent bundle.css. */ /* ------------------------------------------------------------ Police */ /* Alegreya Sans (SIL Open Font License 1.1, voir fonts/OFL.txt), réduite * aux caractères latins et convertie en woff2 (voir docs/identite/README.md). * Embarquée dans le site, donc dans le cache du service worker : elle * fonctionne hors ligne. */ @font-face { font-family: "Alegreya Sans"; src: url("fonts/AlegreyaSans-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: "Alegreya Sans"; src: url("fonts/AlegreyaSans-Italic.woff2") format("woff2"); font-weight: 400; font-style: italic; font-display: swap; } @font-face { font-family: "Alegreya Sans"; src: url("fonts/AlegreyaSans-Medium.woff2") format("woff2"); font-weight: 500; font-style: normal; font-display: swap; } @font-face { font-family: "Alegreya Sans"; src: url("fonts/AlegreyaSans-Bold.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; } @font-face { font-family: "Alegreya Sans"; src: url("fonts/AlegreyaSans-ExtraBold.woff2") format("woff2"); font-weight: 800; font-style: normal; font-display: swap; } /* ------------------------------------------------------------ Couleurs */ /* Thème clair par défaut ; thème sombre selon le système, ou forcé par le * menu (data-theme sur ). Les deux blocs sombres sont identiques * (vérifié par app/tests/ui.test.ts). */ :root { --background: #f5efe5; --surface: #fffcf6; --surface-sunken: #ece3d4; --text: #2b1d15; --muted: #6b5c50; --border: #ded2c0; --border-strong: #8e7d6a; --accent: #a8432b; --on-accent: #ffffff; --accent-soft: #f1d9cf; --focus: #a8432b; --error: #8c1c3a; --verdict-good: #2f6b4f; --verdict-doubtful: #7e5a0f; --verdict-bad: #8c1c3a; --brand-noyer: #4a2e1f; --brand-ivoire: #f3ead8; --brand-laiton: #8f6a1c; --frame: #4a2e1f; --bed: #e9dcc4; --bar: #3f2619; --tray: #3a2418; --point-a: #6b4430; --point-b: #c9ae88; --point-number: #f3ead8; --checker-player: #f7f0e2; --checker-player-edge: #8c7a62; --checker-computer: #2e1c12; --checker-computer-edge: #120a05; --count-player: #2b1d15; --count-computer: #f3ead8; --die-player: #f7f0e2; --pip-player: #2b1d15; --die-computer: #2e1c12; --pip-computer: #f3ead8; --cube: #f7f0e2; --cube-text: #2b1d15; --highlight: #a8432b; --target: rgba(168, 67, 43, 0.32); /* Dernier coup joué (marques et traces) : le laiton, rien d'autre. */ --last-move: var(--brand-laiton); /* Numéros des flèches. La charte les pose sur le cadre (point-number, * ivoire) ; notre plateau les pose sur le fond, où l'ivoire ne se lirait * pas : texte secondaire en thème clair (4,7:1 sur bed), point-number en * thème sombre (6,3:1). */ --point-label: var(--muted); --shadow-raised: 0 1px 2px rgba(43, 29, 21, 0.1); --font-sans: "Alegreya Sans", "Gill Sans", "Segoe UI", system-ui, sans-serif; --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px; --space-6: 24px; --space-8: 32px; --button-height: 48px; --page-width: 40rem; --radius-sm: 6px; --radius-md: 12px; --radius-pill: 999px; /* Mouvement (interaction.md). */ --duration-instant: 90ms; --duration-fast: 160ms; --duration-moderate: 240ms; --easing-standard: cubic-bezier(0.2, 0, 0, 1); --easing-exit: cubic-bezier(0.4, 0, 1, 1); /* Voile sous le menu et les panneaux. */ --scrim: rgba(43, 29, 21, 0.5); /* Hauteurs fixes de l'écran de jeu en portrait : rien ne bouge sous le * doigt (interaction.md, principe 2). */ --topbar-height: 60px; --strip-height: 44px; --infoline-height: 44px; --prompt-height: 74px; --actions-height: 76px; color-scheme: light; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --background: #17110d; --surface: #221913; --surface-sunken: #2c211a; --text: #efe5d5; --muted: #a99886; --border: #3a2d24; --border-strong: #7d6b5b; --accent: #d0694b; --on-accent: #1a110c; --accent-soft: #4a2519; --focus: #e58a6e; --error: #f08fa6; --verdict-good: #7ccba4; --verdict-doubtful: #e0b04f; --verdict-bad: #f08fa6; --brand-laiton: #d6a64a; --frame: #2a1a10; --bed: #4a3626; --bar: #24170e; --tray: #22150d; --point-a: #3a2519; --point-b: #7e6142; --point-number: #cdbfa8; --checker-player: #ede3cf; --checker-player-edge: #8e7c64; --checker-computer: #140d09; --checker-computer-edge: #a8957d; --count-player: #2b1d15; --count-computer: #f3ead8; --die-player: #ede3cf; --pip-player: #2b1d15; --die-computer: #140d09; --pip-computer: #ede3cf; --cube: #ede3cf; --cube-text: #2b1d15; --highlight: #e07a5a; --target: rgba(224, 122, 90, 0.38); --point-label: var(--point-number); --shadow-raised: 0 1px 2px rgba(0, 0, 0, 0.4); --scrim: rgba(0, 0, 0, 0.6); color-scheme: dark; } } :root[data-theme="dark"] { --background: #17110d; --surface: #221913; --surface-sunken: #2c211a; --text: #efe5d5; --muted: #a99886; --border: #3a2d24; --border-strong: #7d6b5b; --accent: #d0694b; --on-accent: #1a110c; --accent-soft: #4a2519; --focus: #e58a6e; --error: #f08fa6; --verdict-good: #7ccba4; --verdict-doubtful: #e0b04f; --verdict-bad: #f08fa6; --brand-laiton: #d6a64a; --frame: #2a1a10; --bed: #4a3626; --bar: #24170e; --tray: #22150d; --point-a: #3a2519; --point-b: #7e6142; --point-number: #cdbfa8; --checker-player: #ede3cf; --checker-player-edge: #8e7c64; --checker-computer: #140d09; --checker-computer-edge: #a8957d; --count-player: #2b1d15; --count-computer: #f3ead8; --die-player: #ede3cf; --pip-player: #2b1d15; --die-computer: #140d09; --pip-computer: #ede3cf; --cube: #ede3cf; --cube-text: #2b1d15; --highlight: #e07a5a; --target: rgba(224, 122, 90, 0.38); --point-label: var(--point-number); --shadow-raised: 0 1px 2px rgba(0, 0, 0, 0.4); --scrim: rgba(0, 0, 0, 0.6); color-scheme: dark; } /* -------------------------------------------------------------- Page */ * { box-sizing: border-box; } /* Pas de « tirer pour rafraîchir » ni de rebond qui recharge la page en * pleine partie ; pas de texte sélectionné par un appui long. */ html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; overscroll-behavior: none; } body { margin: 0 auto; max-width: var(--page-width); padding: 0 var(--space-4); font-family: var(--font-sans); font-size: 17px; line-height: 25px; color: var(--text); background: var(--background); overscroll-behavior: none; user-select: none; -webkit-user-select: none; } [hidden] { display: none !important; } a { color: var(--accent); text-underline-offset: 3px; } /* Anneau de focus clavier, sur tout élément interactif. */ :focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; } /* L'écran de jeu en portrait : des zones de hauteur fixe, de haut en bas ; * la barre d'actions reste collée en bas de l'écran. */ .screen { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; } .game { display: flex; flex: 1; flex-direction: column; } .spacer { flex: 1; } /* Logo clair ou sombre selon le thème. */ .logo-dark { display: none; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .logo-light { display: none; } :root:not([data-theme="light"]) .logo-dark { display: block; } } :root[data-theme="dark"] .logo-light { display: none; } :root[data-theme="dark"] .logo-dark { display: block; } /* -------------------------------------------------------- Barre haute */ .topbar { display: flex; flex: none; gap: var(--space-1); align-items: center; height: var(--topbar-height); } .topbar .brand { flex: 1; display: flex; align-items: center; min-width: 0; margin: 0; } .topbar .brand img { width: auto; max-width: 100%; height: 28px; } /* ------------------------------------------------------- Pictogrammes */ .icon { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; flex: none; } /* ------------------------------------------------------------ Boutons */ /* Ronds comme des pions ; un seul bouton principal (brique) par écran, * les autres en contour. */ button { min-height: var(--button-height); padding: 0 20px; font: inherit; font-weight: 700; color: var(--on-accent); background: var(--accent); border: 2px solid var(--accent); border-radius: var(--radius-pill); cursor: pointer; /* Pas de délai ni de zoom sur un double toucher. */ touch-action: manipulation; -webkit-tap-highlight-color: transparent; transition: background-color var(--duration-instant) var(--easing-standard), filter var(--duration-instant) var(--easing-standard); } button.secondary { color: var(--text); background: transparent; border-color: var(--border-strong); } @media (hover: hover) { button.secondary:hover:not(:disabled) { background: var(--surface-sunken); } } /* Retour visuel au toucher : le bouton descend de 1 px et s'assombrit de * 6 %, sans ombre. */ button:active:not(:disabled) { transform: translateY(1px); filter: brightness(0.94); } button:disabled { opacity: 0.45; cursor: default; } /* Pictogramme seul (ou avec son libellé de 13 px dessous, barre haute). */ .icon-button { display: inline-flex; flex-direction: column; flex: none; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; padding: 0; color: var(--text); background: transparent; border: 0; border-radius: var(--radius-md); } .icon-button.labelled { width: 60px; height: 52px; } .icon-button .label { font-size: 13px; line-height: 15px; font-weight: 500; } @media (hover: hover) { .icon-button:hover:not(:disabled) { background: var(--surface-sunken); } } /* ------------------------------------------- Bandeaux des joueurs */ /* Un bandeau par camp, au-dessus du plateau pour l'ordinateur, dessous pour * vous ; celui qui a la main est teinté. */ .strip { display: flex; flex: none; gap: 10px; align-items: center; height: var(--strip-height); padding: 0 4px 0 12px; border-radius: var(--radius-md); } .strip.turn { background: var(--accent-soft); } .strip .who { flex: 1; min-width: 0; overflow: hidden; font-weight: 700; white-space: nowrap; text-overflow: ellipsis; } .strip .lead { font-size: 15px; line-height: 20px; color: var(--muted); white-space: nowrap; } /* Le compte de points : 20 px gras, chiffres alignés ; il se touche pour * ouvrir la bulle du glossaire. */ .strip .count { min-width: 56px; min-height: 44px; padding: 0 8px; font-size: 20px; line-height: 24px; font-weight: 700; font-variant-numeric: tabular-nums lining-nums; text-align: right; color: var(--text); background: transparent; border: 0; border-radius: var(--radius-md); } .mini { flex: none; width: 18px; height: 18px; border-radius: 50%; } .mini-player { background: var(--checker-player); border: 2px solid var(--checker-player-edge); } .mini-computer { background: var(--checker-computer); border: 2px solid var(--checker-computer-edge); } /* La bulle du compte de points, posée sur le plateau, du côté du bandeau * touché : elle ne déplace rien. */ .board-box { position: relative; flex: none; } /* Téléphone en portrait : le plateau, héros de l'écran, prend la largeur * presque entière (8 px de marge au lieu de 16). */ @media (max-width: 40rem) { html:not(.landscape) .board-box { margin-inline: calc(var(--space-2) - var(--space-4)); } } .bubble { position: absolute; left: var(--space-2); right: var(--space-2); z-index: 5; margin: 0; padding: 10px 14px; font-size: 15px; line-height: 20px; color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-raised); animation: fade-in var(--duration-fast) var(--easing-standard); } .bubble[data-side="computer"] { top: var(--space-2); } .bubble[data-side="player"] { bottom: var(--space-2); } .bubble p { margin: 0 0 var(--space-1); } .bubble-term { font-weight: 700; } .link-button { min-height: 44px; padding: 0; color: var(--accent); background: transparent; border: 0; border-radius: 0; text-decoration: underline; text-underline-offset: 3px; } /* ----------------------------------------------- Sous le plateau */ /* Ligne d'information, toujours réservée : ce qui vient de se passer (coup * de l'ordinateur, jet d'ouverture, chargement), et « Revoir » au bout. */ .infoline { display: flex; flex: none; gap: var(--space-2); align-items: center; height: var(--infoline-height); padding-left: 12px; } .info { display: -webkit-box; flex: 1; margin: 0; overflow: hidden; font-size: 15px; line-height: 20px; color: var(--muted); -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; } .infoline .replay { color: var(--accent); } /* La consigne du moment : ce qui doit ressortir de l'écran. Hauteur fixe * (deux lignes) ; fond d'accent léger quand c'est au joueur. */ .prompt { flex: none; height: var(--prompt-height); margin: 0; padding: var(--space-3) var(--space-4); overflow: hidden; font-weight: 700; background: var(--accent-soft); border-radius: var(--radius-md); } .prompt.neutral, body.busy .prompt { font-weight: 400; background: var(--surface-sunken); } /* L'ordinateur réfléchit : trois points qui apparaissent l'un après * l'autre (la seule animation en boucle). */ .prompt.thinking::after { content: ""; animation: thinking 1.2s steps(4, end) infinite; } @keyframes thinking { 0% { content: ""; } 25% { content: "."; } 50% { content: ".."; } 75% { content: "..."; } } /* Barre d'actions collée en bas : l'action secondaire à gauche, la * principale à droite, sous le pouce. */ .actions { position: sticky; bottom: 0; z-index: 2; display: grid; flex: none; grid-template-columns: 1fr 1.6fr; gap: var(--space-2); height: var(--actions-height); padding: var(--space-3) 0 var(--space-4); background: var(--background); border-top: 1px solid var(--border); } .actions .slot { display: flex; min-width: 0; } .actions .slot button { flex: 1; min-width: 0; padding: 0 12px; display: inline-flex; gap: 6px; align-items: center; justify-content: center; } .actions .slot .icon { width: 20px; height: 20px; } .move-hint { align-self: center; margin: 0; font-size: 15px; line-height: 20px; color: var(--muted); text-align: center; } /* --------------------------------------------------- Fenêtres */ /* Voile sous le menu et les panneaux : il assombrit l'écran derrière. */ .veil { position: fixed; inset: 0; z-index: 10; display: flex; align-items: center; justify-content: center; padding: var(--space-4); background: var(--scrim); animation: fade-in var(--duration-fast) var(--easing-standard); } /* Le menu : une feuille qui monte du bas. */ .sheet-veil { align-items: flex-end; padding: 0; } .sheet { width: min(100%, var(--page-width)); max-height: 100%; overflow-y: auto; padding: var(--space-2) var(--space-4) var(--space-6); color: var(--text); background: var(--surface); border-radius: 20px 20px 0 0; box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.2); animation: sheet-up var(--duration-moderate) var(--easing-standard); } .sheet-head { position: relative; display: flex; align-items: center; justify-content: space-between; min-height: 52px; } .grip { position: absolute; top: 0; left: 50%; width: 40px; height: 4px; margin-left: -20px; background: var(--border-strong); border-radius: 2px; } .sheet-title { margin: 0; font-size: 20px; line-height: 26px; } .sheet .item { display: flex; gap: 14px; align-items: center; width: 100%; min-height: 52px; padding: 0; font-weight: 500; text-align: left; color: var(--text); background: transparent; border: 0; border-bottom: 1px solid var(--border); border-radius: 0; } .sheet .item:last-child { border-bottom: 0; } .sheet .item .icon { color: var(--muted); } .item-value { margin-left: auto; font-size: 15px; color: var(--muted); } /* Interrupteur (Vibrations, écran allumé). */ .switch { position: relative; flex: none; width: 44px; height: 26px; margin-left: auto; background: var(--border-strong); border-radius: 13px; transition: background-color var(--duration-fast) var(--easing-standard); } .switch::after { content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; background: var(--surface); border-radius: 50%; transition: transform var(--duration-fast) var(--easing-standard); } .item[aria-checked="true"] .switch { background: var(--accent); } .item[aria-checked="true"] .switch::after { background: var(--on-accent); transform: translateX(18px); } /* Panneau centré : confirmation du double, fin de partie, double de * l'ordinateur en paysage. */ .panel { width: min(24rem, 100%); padding: var(--space-4); color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-raised); animation: panel-in var(--duration-moderate) var(--easing-standard); } .panel p { margin: 0 0 var(--space-4); font-size: 20px; line-height: 26px; font-weight: 700; } .panel-actions { display: flex; gap: var(--space-2); } .panel-actions button { flex: 1 1 0; padding: 0 12px; } /* « Nouvelle partie commencée. Reprendre l'ancienne », 10 s, avec sa * barre de temps. */ .banner { position: fixed; left: 50%; bottom: calc(var(--actions-height) + var(--space-2)); z-index: 9; display: flex; gap: var(--space-3); align-items: center; width: min(24rem, calc(100% - 2 * var(--space-4))); padding: var(--space-2) var(--space-3) var(--space-3); overflow: hidden; font-size: 15px; line-height: 20px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-raised); transform: translateX(-50%); animation: fade-in var(--duration-fast) var(--easing-standard); } .banner span:first-child { flex: 1; } .banner button { flex: none; min-height: 44px; padding: 0 14px; } .banner-timer { position: absolute; left: 0; bottom: 0; width: 100%; height: 4px; background: var(--accent); transform-origin: left; } .banner-timer.running { animation: banner-timer 10s linear forwards; } @keyframes banner-timer { from { transform: scaleX(1); } to { transform: scaleX(0); } } @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes sheet-up { from { transform: translateY(100%); } to { transform: translateY(0); } } @keyframes panel-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } /* Mouvement réduit : tout est instantané, rien ne roule ni ne glisse ; la * barre de temps reste visible, immobile. */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0s !important; transition-duration: 0s !important; } .prompt.thinking::after { animation: none; content: "…"; } .banner-timer.running { animation: none; } button:active:not(:disabled) { transform: none; } } /* ------------------------------------------------------------ Plateau */ .board { display: block; width: 100%; height: auto; aspect-ratio: 640 / 520; user-select: none; -webkit-user-select: none; touch-action: manipulation; -webkit-tap-highlight-color: transparent; font-family: var(--font-sans); /* Alegreya Sans dessine par défaut des chiffres elzéviriens (de hauteurs * variables) : sur le plateau, des chiffres alignés se lisent mieux. */ font-variant-numeric: tabular-nums lining-nums; } .board-frame { fill: var(--frame); } .board-bed { fill: var(--bed); } .board-bar { fill: var(--bar); } .board-tray { fill: var(--tray); } .point-a { fill: var(--point-a); } .point-b { fill: var(--point-b); } /* Numéros des flèches : leur taille est une mesure du dessin (attribut * font-size), calculée pour faire au moins 12 px à l'écran (geometry.ts). */ .point-number { fill: var(--point-label); font-weight: 500; text-anchor: middle; } .checker { stroke-width: 2; } .checker-player { fill: var(--checker-player); stroke: var(--checker-player-edge); } .checker-computer { fill: var(--checker-computer); stroke: var(--checker-computer-edge); } /* Filet intérieur des pions (bundle.css), prêt pour le jour où le plateau * le dessine. */ .checker-ring { fill: none; stroke-width: 1.5; } .ring-player { stroke: var(--checker-player-edge); } .ring-computer { stroke: var(--checker-computer-edge); } .checker.movable { stroke: var(--highlight); stroke-width: 3; } .checker.selected { stroke: var(--highlight); stroke-width: 6; } .checker-count { font-size: 18px; font-weight: 700; text-anchor: middle; } .count-player { fill: var(--count-player); } .count-computer { fill: var(--count-computer); } .target-zone { fill: var(--target); } /* Le dernier coup de l'ordinateur (couleur laiton, charte) : une flèche par * demi-coup, les pions arrivés et frappés entourés, un pion fantôme là où * un pion est parti. */ .trace-arrow { stroke: var(--last-move); stroke-width: 5; stroke-linecap: round; opacity: 0.85; } .trace-head { fill: var(--last-move); } .trace-landed, .trace-hit { fill: none; stroke: var(--last-move); stroke-width: 4; } .trace-hit { stroke-dasharray: 6 4; } .trace-ghost { fill: none; stroke: var(--last-move); stroke-width: 2.5; stroke-dasharray: 5 4; } .die-player { fill: var(--die-player); stroke: var(--checker-player-edge); stroke-width: 1.5; } .die-computer { fill: var(--die-computer); stroke: var(--checker-computer-edge); stroke-width: 1.5; } .pip-player { fill: var(--pip-player); } .pip-computer { fill: var(--pip-computer); } /* Dés du joueur en attente d'être lancés, et videau quand il peut doubler : * ils se touchent comme les boutons. */ .die-waiting rect { stroke: var(--highlight); stroke-width: 2.5; stroke-dasharray: 5 4; } .cube.can-double .cube-face { stroke: var(--highlight); stroke-width: 3; } /* Jet sans coup possible : dés estompés et barrés. */ .die-blocked { opacity: 0.5; } .die-strike { stroke: var(--text); stroke-width: 3; stroke-linecap: round; } /* Dé déjà utilisé par un demi-coup du coup en cours : estompé, sans être * barré (il n'est pas perdu : « Annuler » le rend). */ .die-used { opacity: 0.35; } .cube-face { fill: var(--cube); stroke: var(--checker-player-edge); stroke-width: 2; } .cube-value { fill: var(--cube-text); font-size: 17px; font-weight: 800; text-anchor: middle; } .hit { fill: transparent; cursor: pointer; } /* Paysage : numéros sur le cadre (ivoire), comptes de points en pastilles * aux bouts de la barre, consigne dans la bande, commandes à gauche. */ .point-number.on-frame { fill: var(--point-number); } .pip-chip { stroke-width: 1.5; } .chip-player { fill: var(--checker-player); stroke: var(--checker-player-edge); } .chip-computer { fill: var(--checker-computer); stroke: var(--checker-computer-edge); } .pip-chip-text { font-weight: 700; text-anchor: middle; } .chip-text-player { fill: var(--pip-player); } .chip-text-computer { fill: var(--pip-computer); } .band-pill { fill: var(--accent-soft); } .band-text { fill: var(--text); font-weight: 700; text-anchor: middle; } .control-circle { fill: none; stroke: var(--point-number); stroke-width: 2; } .control-icon { fill: none; stroke: var(--point-number); stroke-width: 2px; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; } .control.disabled { opacity: 0.35; } /* ------------------------------------------------------- Mode paysage */ /* Téléphone tourné (ADR 0012) : le plateau est l'écran, sur la hauteur * réelle (barre d'adresse comprise), cadre noyer jusqu'aux bords. La * classe vient de app.ts (rotation du téléphone, ou repli du plein écran). */ html.landscape, html.landscape body { height: 100%; overflow: hidden; } html.landscape body { max-width: none; padding: 0; background: var(--frame); } html.landscape .topbar, html.landscape .strip, html.landscape .infoline, html.landscape .prompt, html.landscape .spacer, html.landscape .actions { display: none; } html.landscape .board-box { position: fixed; inset: 0; } html.landscape .board { width: 100%; height: 100%; aspect-ratio: auto; } html.landscape .banner { bottom: var(--space-2); } /* L'aide reste une page qu'on fait défiler. */ html.landscape.help-open, html.landscape.help-open body { height: auto; overflow: visible; } html.landscape.help-open body { padding: 0 var(--space-4); background: var(--background); } /* Repli du plein écran : le paysage ne peut pas être verrouillé, l'écran * entier tourne d'un quart de tour dans le portrait. Les touchers suivent * la rotation ; le plateau et les fenêtres sont posés dans #screen. */ html.rotated .screen { position: fixed; top: 0; left: 0; width: 100vh; width: 100dvh; height: 100vw; min-height: 0; overflow: hidden; transform-origin: top left; transform: rotate(90deg) translateY(-100%); } html.rotated .board-box, html.rotated .veil { position: absolute; } html.rotated .banner { position: absolute; } /* --------------------------------------------------------------- Aide */ .help { max-width: var(--page-width); margin: 0 auto; } .help h2 { margin: var(--space-8) 0 var(--space-2); font-size: 24px; line-height: 30px; font-weight: 700; } .help h3 { margin: var(--space-6) 0 var(--space-1); font-size: 20px; line-height: 26px; font-weight: 700; } .help p { margin: var(--space-2) 0; } .steps { margin: var(--space-2) 0; padding-left: var(--space-6); } .steps li + li { margin-top: var(--space-1); } .steps li::marker { color: var(--muted); } /* Glossaire : une liste de définitions, sur une carte. */ .glossary { margin: var(--space-3) 0 0; padding: var(--space-1) var(--space-4); background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: var(--shadow-raised); } .glossary dt { padding-top: var(--space-3); font-weight: 700; } .glossary dd { margin: 0; padding-bottom: var(--space-3); } .glossary dd + dt { border-top: 1px solid var(--border); } .about { margin-top: var(--space-8); font-size: 15px; line-height: 20px; color: var(--muted); } .help { user-select: text; -webkit-user-select: text; }