From e2cc38686febac0fa14c9b60e91946d4659db88d Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Mon, 6 Apr 2026 20:11:24 -0400 Subject: [PATCH] XL landscape: revert tray to landscape style; fix sig-stage stretch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove _tray.scss XL (≥1800px) portrait override block entirely - _isLandscape() no longer returns false at ≥1800px — tray uses landscape slide-from-top at all wide landscape widths - sig-stage: align-self: stretch (was center) so JS sizeSigCard() measures correct stage width; card size no longer collapses - Position strip: horizontal row at top (was vertical column-reverse) - sig-overlay/sig-stage/sig-deck-grid layout polish at 1100px/1800px Co-Authored-By: Claude Sonnet 4.6 --- src/apps/epic/static/apps/epic/tray.js | 8 +- src/static_src/scss/_applets.scss | 10 +++ src/static_src/scss/_base.scss | 117 +++++++++++++++++++------ src/static_src/scss/_button-pad.scss | 7 ++ src/static_src/scss/_room.scss | 67 +++++++++----- src/static_src/scss/_tray.scss | 74 +--------------- 6 files changed, 152 insertions(+), 131 deletions(-) diff --git a/src/apps/epic/static/apps/epic/tray.js b/src/apps/epic/static/apps/epic/tray.js index 74a4889..3aa9439 100644 --- a/src/apps/epic/static/apps/epic/tray.js +++ b/src/apps/epic/static/apps/epic/tray.js @@ -40,9 +40,6 @@ var Tray = (function () { function _isLandscape() { if (_landscapeOverride !== null) return _landscapeOverride; - // ≥1800px uses portrait-style tray (slides from right) to match the - // doubled sidebar widths and XL tray CSS reset. - if (window.innerWidth >= 1800) return false; return window.innerWidth > window.innerHeight; } @@ -97,10 +94,7 @@ var Tray = (function () { // Closed: tray hidden above viewport, handle visible at y=0. _maxTop = -(gearBtnTop - handleH); } else { - // Portrait (and XL landscape, which uses portrait-style tray): - // Wrap width = viewportW so the closed right edge reaches the viewport boundary. - // The footer sidebar (z-100) is above the wrap (z-95) and has a solid background, - // so the handle parks behind it and slides out from under it when opened. + // Portrait: wrap width = full viewport; handle parks at right edge. var handleW = _btn.offsetWidth || 48; if (_wrap) _wrap.style.width = window.innerWidth + 'px'; _minLeft = 0; diff --git a/src/static_src/scss/_applets.scss b/src/static_src/scss/_applets.scss index 3fb7e15..7be4513 100644 --- a/src/static_src/scss/_applets.scss +++ b/src/static_src/scss/_applets.scss @@ -234,6 +234,16 @@ black 99%, transparent 100% ); + margin-left: 1rem; + margin-top: 1rem; + @media (orientation: landscape) and (min-width: 900px) { + margin-left: 2rem; + margin-top: 2rem; + } + @media (orientation: landscape) and (min-width: 1800px) { + margin-left: 4rem; + margin-top: 4rem; + } section { @extend %applet-box; diff --git a/src/static_src/scss/_base.scss b/src/static_src/scss/_base.scss index 57ef40a..32802b2 100644 --- a/src/static_src/scss/_base.scss +++ b/src/static_src/scss/_base.scss @@ -193,6 +193,16 @@ body { } } +@media (orientation: landscape) and (max-width: 1100px) { + body .container { + .navbar { + h1 { + font-size: 1rem !important; + } + } + } +} + @media (orientation: landscape) { $sidebar-w: 5rem; @@ -265,12 +275,12 @@ body { .navbar-label { opacity: 0.7; } } - .btn-primary { - width: 4rem; - height: 4rem; - font-size: 0.875rem; - border-width: 0.21rem; - } + // .btn-primary { + // width: 4rem; + // height: 4rem; + // font-size: 0.875rem; + // border-width: 0.21rem; + // } // Login form: offset from fixed sidebars in landscape .input-group { @@ -300,17 +310,23 @@ body { padding: 0 0.5rem; } - // Header row: compact in landscape + // Header row: h2 rotates into the left gutter (just right of the navbar border). + // position:fixed takes h2 out of flow; .row collapses to zero height automatically. body .container .row { - padding: 0.25rem 0; - - .col-lg-6 h2 { - font-size: 1.5rem; - margin: 0 0 0.25rem; - letter-spacing: 0.4em; - text-align: center; - text-align-last: left; - } + padding: 0; + margin: 0; + } + body .container .row .col-lg-6 h2 { + position: fixed; + left: 5rem; // $sidebar-w — flush with the navbar right border + top: 50%; + transform: translateY(-50%) rotate(180deg); + writing-mode: vertical-rl; + font-size: 1.5rem; + letter-spacing: 0.4em; + margin: 0; + z-index: 85; + pointer-events: none; } // Footer → fixed right sidebar (mirrors navbar approach — explicit right boundary) @@ -336,7 +352,8 @@ body { flex-direction: column-reverse; width: auto; max-width: none; - gap: 3rem; + gap: 1.5rem !important; + margin-bottom: 4rem; a { font-size: 1.75rem; @@ -348,13 +365,49 @@ body { .footer-container { position: absolute; - top: 0.75rem; + top: 0.25rem; text-align: center; - font-size: 1rem; - line-height: 1.4; + line-height: 0.75 !important; color: rgba(var(--secUser), 1); br { display: block; } + + small { + font-size: 0.75rem !important; + } + } + } +} + +@media (orientation: landscape) and (min-width: 700px) { + body .container .row .col-lg-6 h2 { + @media (min-height: 400px) { + font-size: 2.5rem; + } + @media (min-height: 500px) { + font-size: 3rem; + } + } + + body #id_footer { + #id_footer_nav { + gap: 3rem !important; + + a { + font-size: 1.75rem; + display: flex; + justify-content: center; + align-items: center; + } + } + + .footer-container { + line-height: 1; + margin-top: 0.5rem; + + small { + font-size: 1rem; + } } } } @@ -373,7 +426,7 @@ body { .navbar-brand h1 { font-size: 2.4rem; } .navbar-text { font-size: 0.78rem; } // 0.65rem × 1.2 - .btn-primary { width: 4rem; height: 4rem; font-size: 0.875rem; } + // .btn-primary { width: 4rem; height: 4rem; font-size: 0.875rem; } .input-group { left: $sidebar-xl; @@ -386,23 +439,31 @@ body { margin-right: $sidebar-xl; } - // h2 page title: portrait-style — centred and full-size on a wide canvas + // h2 page title: keep vertical rotation; shift left to clear the wider XL navbar. body .container .row .col-lg-6 h2 { - font-size: 4rem; - letter-spacing: 1em; - text-align: center; - text-align-last: center; + left: 8rem; // $sidebar-xl + @media (min-height: 800px) { + font-size: 4.5rem; + } } body #id_footer { width: $sidebar-xl; #id_footer_nav { - gap: 8rem; + gap: 8rem !important; a { font-size: 3rem; } } - .footer-container { font-size: 0.85rem; } + .footer-container { + font-size: 0.85rem; + margin-top: 1rem; + + + small { + font-size: 1.2rem; + } + } } } diff --git a/src/static_src/scss/_button-pad.scss b/src/static_src/scss/_button-pad.scss index be45654..34cdb3d 100644 --- a/src/static_src/scss/_button-pad.scss +++ b/src/static_src/scss/_button-pad.scss @@ -61,6 +61,13 @@ 0 0 0.5rem rgba(var(--quaUser), 0.22) ; } + + @media (orientation: landscape) and (max-width: 1100px) { + width: 2.75rem !important; + height: 2.75rem !important; + font-size: 0.625rem !important; + border-width: 0.125rem !important; + } } &.btn-abandon { diff --git a/src/static_src/scss/_room.scss b/src/static_src/scss/_room.scss index 1b8a191..837b2bc 100644 --- a/src/static_src/scss/_room.scss +++ b/src/static_src/scss/_room.scss @@ -809,29 +809,23 @@ $card-h: 60px; z-index: 50; } - // Reflow position strip into a vertical column along the left edge, - // reversed so 6 is at top, 1 at bottom, below the GAMEROOM title. + // Position strip: horizontal row across the top, slots 1-6 in order. + // Offset from both sidebars (5rem each) and centred with gap. .position-strip { - flex-direction: column-reverse; - top: 3rem; - left: 0.5rem; - right: auto; + flex-direction: row; + top: 2.5rem; + left: 5rem; + right: 5rem; + justify-content: center; gap: round($gate-gap * 0.4); } - // Shallow landscape (phones): wrap into two columns — left: 6,5,4 / right: 3,2,1 - // Columns grow rightward (wrap, not wrap-reverse) so overflow: hidden doesn't clip. - // order: -1 on slots 4–6 pulls them to the front of the flex sequence; combined - // with column-reverse they land in the left column reading 6,5,4 top-to-bottom. + // Small landscape (phones ≤550px tall): strip stays horizontal — no two-column + // trick needed now that the h2 is in the gutter. Just clear any order overrides. @media (max-height: 550px) { .position-strip { - flex-wrap: wrap; - // cap height to exactly 3 circles so the 4th wraps to a new column - max-height: #{3 * round($gate-node * 0.75) + 2 * round($gate-gap * 0.4)}; - - .gate-slot[data-slot="4"], - .gate-slot[data-slot="5"], - .gate-slot[data-slot="6"] { order: -1; } + .gate-slot { order: 0; } + top: 1rem; } } @@ -1084,23 +1078,50 @@ html:has(.sig-backdrop) { // Grid margins reset to 0 — overlay padding handles all edge clearance. @media (orientation: landscape) { - .sig-overlay { padding-left: 4rem; } - .sig-modal { max-width: none; } + .sig-modal { + max-width: none; + flex-direction: row; // grid to the right, stage + card preview to the left + margin-left: 4rem; + margin-right: 3rem; + } + .sig-stage { + min-width: 0; // allow shrinking in row layout; align-items:flex-end already set + } .sig-deck-grid { - grid-template-columns: repeat(9, 3rem); + grid-template-columns: repeat(6, 2.5rem); margin: 0; + align-self: flex-end; // sit at the bottom of the modal row } } -@media (orientation: landscape) and (min-width: 1100px) { +@media (orientation: landscape) and (min-width: 900px) { + // Wide landscape: revert to stacked layout (stage top, 18-card row grid bottom). + .sig-modal { + flex-direction: column; + align-items: stretch; + } + .sig-stage { + min-width: auto; + align-self: stretch; // fill full modal width so JS sizeSigCard() gets correct stageWidth + margin-left: 3rem; + } .sig-deck-grid { grid-template-columns: repeat(18, 3rem); + align-self: center; } } @media (orientation: landscape) and (min-width: 1800px) { - // Sig overlay: clear doubled navbar sidebar (8rem instead of 4rem) - .sig-overlay { padding-left: 8rem; } + // Sig overlay: clear doubled sidebars (8rem each instead of 4rem/6rem) + .sig-overlay { padding-left: 8rem; padding-right: 8rem; } + .sig-stage { + align-self: stretch; // fill full modal width so JS sizeSigCard() gets correct stageWidth + margin-left: 3rem; + } + .sig-deck-grid { + grid-template-columns: repeat(18, 5rem); + align-self: center; + } // Room menu: base right: 0.5rem (same-specificity ID rule) overrides _applets.scss // XL block because _room.scss is imported later. Re-declare here to win the cascade. diff --git a/src/static_src/scss/_tray.scss b/src/static_src/scss/_tray.scss index 5abd493..c75c8f8 100644 --- a/src/static_src/scss/_tray.scss +++ b/src/static_src/scss/_tray.scss @@ -329,76 +329,4 @@ $handle-r: 1rem; } } -// ── XL landscape (≥1800px): portrait-style tray — slides in from right ───── -// Overrides all landscape rules above. JS also returns false from _isLandscape() -// at this width so portrait code paths run throughout. -@media (orientation: landscape) and (min-width: 1800px) { - #id_tray_wrap { - flex-direction: row; - top: 0; - bottom: 0; - left: auto; // JS controls left; width set to innerWidth so wrap fills viewport - right: auto; - height: auto; - width: auto; - z-index: 95; // below footer/nav sidebars (z-100) — opaque footer masks the tray - transition: left 0.35s cubic-bezier(0.4, 0, 0.2, 1); - - &.wobble { animation: tray-wobble 0.45s ease; } - &.snap { animation: tray-snap 0.30s ease; } - } - - #id_tray_handle { - width: $handle-exposed; // 48px portrait strip - height: auto; - } - - #id_tray_grip { - top: 50%; - bottom: auto; - left: calc(#{$handle-exposed} / 2 - 0.125rem); - transform: translateY(-50%); - width: $handle-rect-w; // 10000px extends leftward - height: $handle-rect-h; // 72px - } - - #id_tray { - border-left: 2.5rem solid rgba(var(--quaUser), 1); - border-top: 2.5rem solid rgba(var(--quaUser), 1); - border-bottom: 2.5rem solid rgba(var(--quaUser), 1); - border-right: none; - margin-left: 0.5rem; - margin-bottom: 0; - width: auto; - max-width: none; - align-self: auto; - flex: 1; - height: auto; - overflow: hidden; - box-shadow: - -0.25rem 0 0.5rem rgba(0, 0, 0, 0.55), - inset 0 0 0 0.3rem rgba(var(--quiUser), 0.45), - inset 0.6rem 0 1.5rem -0.5rem rgba(0, 0, 0, 1), - inset 0.6rem 0 1.5rem -0.5rem rgba(var(--quiUser), 0.5), - inset 0 0.6rem 1.5rem -0.5rem rgba(0, 0, 0, 1), - inset 0 0.6rem 1.5rem -0.5rem rgba(var(--quiUser), 0.5), - inset 0 -0.6rem 1.5rem -0.5rem rgba(0, 0, 0, 1), - inset 0 -0.6rem 1.5rem -0.5rem rgba(var(--quiUser), 0.5) - ; - } - - #id_tray_grid { - grid-template-columns: none; - grid-template-rows: repeat(8, var(--tray-cell-size, 48px)); - grid-auto-flow: column; - grid-auto-columns: var(--tray-cell-size, 48px); - grid-auto-rows: auto; - position: static; - } - - .tray-cell { - border-top: none; - border-right: 2px dotted rgba(var(--priUser), 0.35); - border-bottom: 2px dotted rgba(var(--priUser), 0.35); - } -} +// ≥1800px uses the same landscape tray rules as narrower landscape — no override block needed.