comparison mrjunejune/src/jrpg/jrpg.css @ 264:04fee26ecce0

add authenticated JRPG conversation platform Add reusable auth/session storage, owned conversation recovery, guest quotas, admin workflows, URL-routed conversation UI, mobile frame support, and parallel browser acceptance. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 07:34:12 -0700
parents ee04e4e69fed
children 41a49c29a28f
comparison
equal deleted inserted replaced
263:ee04e4e69fed 264:04fee26ecce0
103 --mjj-frame-telemetry-height: 4.8%; 103 --mjj-frame-telemetry-height: 4.8%;
104 --mjj-frame-temp-value-inline: 12%; 104 --mjj-frame-temp-value-inline: 12%;
105 --mjj-frame-user-value-inline: 32.5%; 105 --mjj-frame-user-value-inline: 32.5%;
106 --mjj-frame-status-value-inline: 60.5%; 106 --mjj-frame-status-value-inline: 60.5%;
107 --mjj-frame-uptime-value-inline: 88%; 107 --mjj-frame-uptime-value-inline: 88%;
108 --mjj-frame-dog-bar-block-end: 4%; 108 --mjj-frame-dog-bar-block-end: 0%;
109 --mjj-frame-dog-bar-height: 31%; 109 --mjj-frame-dog-bar-height: 100%;
110 box-sizing: border-box; 110 box-sizing: border-box;
111 display: grid; 111 display: grid;
112 place-items: center; 112 place-items: center;
113 width: 100%; 113 width: 100%;
114 max-width: none; 114 max-width: none;
352 inset: auto 0 var(--mjj-frame-dog-bar-block-end); 352 inset: auto 0 var(--mjj-frame-dog-bar-block-end);
353 height: var(--mjj-frame-dog-bar-height); 353 height: var(--mjj-frame-dog-bar-height);
354 background-image: var(--mjj-jrpg-art); 354 background-image: var(--mjj-jrpg-art);
355 background-position: center; 355 background-position: center;
356 background-repeat: no-repeat; 356 background-repeat: no-repeat;
357 background-size: 100% 100%; 357 background-size: cover;
358 content: ""; 358 content: "";
359 image-rendering: pixelated; 359 image-rendering: pixelated;
360 pointer-events: none; 360 pointer-events: none;
361 } 361 }
362 362
414 gap: var(--zenbu-sys-space-group); 414 gap: var(--zenbu-sys-space-group);
415 padding-bottom: var(--zenbu-sys-padding-sm); 415 padding-bottom: var(--zenbu-sys-padding-sm);
416 border-bottom: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft); 416 border-bottom: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
417 } 417 }
418 418
419 .jrpg-preview-kicker,
420 .jrpg-menu-label, 419 .jrpg-menu-label,
421 .jrpg-brand > p, 420 .jrpg-brand > p,
422 .jrpg-dialog-heading p { 421 .jrpg-dialog-heading p {
423 color: var(--mjj-jrpg-text-muted); 422 color: var(--mjj-jrpg-text-muted);
424 font-size: var(--zenbu-sys-font-size-xs); 423 font-size: var(--zenbu-sys-font-size-xs);
557 display: grid; 556 display: grid;
558 grid-template-rows: minmax(0, 1fr); 557 grid-template-rows: minmax(0, 1fr);
559 gap: 0; 558 gap: 0;
560 padding: var(--zenbu-sys-padding-md); 559 padding: var(--zenbu-sys-padding-md);
561 background: var(--mjj-jrpg-surface); 560 background: var(--mjj-jrpg-surface);
561 overflow: hidden;
562 }
563
564 .jrpg-utility > mjj-jrpg-preview,
565 .jrpg-utility > mjj-conversation-archive {
566 box-sizing: border-box;
567 grid-column: 1;
568 grid-row: 1;
569 width: 100%;
570 height: 100%;
571 min-height: 0;
572 min-width: 0;
562 } 573 }
563 574
564 .jrpg-brand { 575 .jrpg-brand {
565 display: flex; 576 display: flex;
566 align-items: end; 577 align-items: end;
611 white-space: nowrap; 622 white-space: nowrap;
612 } 623 }
613 624
614 .jrpg-preview-panel { 625 .jrpg-preview-panel {
615 display: grid; 626 display: grid;
616 grid-template-rows: auto auto auto minmax(0, 1fr) auto; 627 grid-template-rows: auto auto minmax(0, 1fr) auto;
617 gap: var(--zenbu-sys-space-group); 628 gap: var(--zenbu-sys-space-group);
618 height: 100%; 629 height: 100%;
619 padding: var(--zenbu-sys-padding-lg); 630 padding: var(--zenbu-sys-padding-lg);
620 background: 631 background:
621 linear-gradient( 632 linear-gradient(
635 646
636 .jrpg-preview-panel h2 { 647 .jrpg-preview-panel h2 {
637 color: var(--mjj-jrpg-primary); 648 color: var(--mjj-jrpg-primary);
638 } 649 }
639 650
640 .jrpg-preview-panel > p:not(.jrpg-preview-kicker) { 651 .jrpg-preview-panel > p {
641 color: var(--mjj-jrpg-text); 652 color: var(--mjj-jrpg-text);
642 } 653 }
643 654
644 .jrpg-work-showcase { 655 .jrpg-work-showcase {
645 display: grid; 656 display: grid;
1505 .jrpg-utility, 1516 .jrpg-utility,
1506 mjj-jrpg-composer, 1517 mjj-jrpg-composer,
1507 mjj-jrpg-menu 1518 mjj-jrpg-menu
1508 ), 1519 ),
1509 .jrpg-scene > mjj-jrpg-chat, 1520 .jrpg-scene > mjj-jrpg-chat,
1510 .jrpg-utility > mjj-jrpg-preview > .jrpg-preview-panel { 1521 .jrpg-utility > mjj-jrpg-preview > .jrpg-preview-panel,
1522 .jrpg-utility > mjj-conversation-archive {
1511 border: 0; 1523 border: 0;
1512 background-color: transparent; 1524 background-color: transparent;
1513 box-shadow: none; 1525 box-shadow: none;
1514 } 1526 }
1515 1527
1640 min-height: 34rem; 1652 min-height: 34rem;
1641 } 1653 }
1642 1654
1643 .jrpg-utility { 1655 .jrpg-utility {
1644 min-height: 27rem; 1656 min-height: 27rem;
1657 overflow: hidden;
1645 } 1658 }
1646 1659
1647 mjj-jrpg-menu nav { 1660 mjj-jrpg-menu nav {
1648 grid-template-columns: 1fr; 1661 grid-template-columns: 1fr;
1649 } 1662 }
1651 .jrpg-menu-label { 1664 .jrpg-menu-label {
1652 writing-mode: initial; 1665 writing-mode: initial;
1653 } 1666 }
1654 1667
1655 mjj-jrpg-menu ul { 1668 mjj-jrpg-menu ul {
1656 grid-template-columns: repeat(3, minmax(0, 1fr)); 1669 grid-template-columns: repeat(2, minmax(0, 1fr));
1657 } 1670 }
1658 } 1671 }
1659 1672
1660 @media (max-width: 34rem) { 1673 @media (max-width: 34rem) {
1661 .jrpg-main { 1674 .jrpg-main {
1782 .jrpg-tool-pane { 1795 .jrpg-tool-pane {
1783 min-height: 24rem; 1796 min-height: 24rem;
1784 } 1797 }
1785 1798
1786 mjj-jrpg-menu ul { 1799 mjj-jrpg-menu ul {
1787 grid-template-columns: 1fr; 1800 grid-template-columns: repeat(2, minmax(0, 1fr));
1788 } 1801 }
1789 1802
1790 .jrpg-preview-dialog dialog { 1803 .jrpg-preview-dialog dialog {
1791 width: calc(100% - var(--zenbu-sys-space-group)); 1804 width: calc(100% - var(--zenbu-sys-space-group));
1792 max-width: none; 1805 max-width: none;
1828 .jrpg-page::-webkit-scrollbar-button, 1841 .jrpg-page::-webkit-scrollbar-button,
1829 .jrpg-page *::-webkit-scrollbar-button { 1842 .jrpg-page *::-webkit-scrollbar-button {
1830 display: none; 1843 display: none;
1831 } 1844 }
1832 1845
1846 /* ================================================================
1847 Archive component — placed in utility panel (top-right)
1848 ================================================================ */
1849
1850 mjj-jrpg-chat {
1851 grid-column: 2;
1852 grid-row: 1;
1853 }
1854
1855 mjj-conversation-archive {
1856 position: relative;
1857 z-index: 1;
1858 display: grid;
1859 grid-template-rows: auto auto minmax(0, 1fr) auto auto;
1860 align-self: stretch;
1861 min-height: 0;
1862 padding: var(--zenbu-sys-padding-md);
1863 overflow: hidden;
1864 background: var(--mjj-jrpg-panel-strong);
1865 box-shadow: inset 0 0 0 var(--zenbu-sys-stroke-width) var(--mjj-jrpg-info);
1866 }
1867
1868 mjj-conversation-archive[hidden] {
1869 display: none;
1870 }
1871
1872 .jrpg-utility > mjj-conversation-archive {
1873 border: 0;
1874 box-shadow: inset 0 0 0 var(--zenbu-sys-stroke-width) var(--mjj-jrpg-info);
1875 }
1876
1877 .jrpg-archive-heading {
1878 display: flex;
1879 align-items: baseline;
1880 justify-content: space-between;
1881 gap: var(--zenbu-sys-space-group);
1882 padding-bottom: var(--zenbu-sys-padding-sm);
1883 border-bottom: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
1884 }
1885
1886 .jrpg-archive-heading h2 {
1887 margin: 0;
1888 color: var(--mjj-jrpg-text);
1889 font-size: var(--zenbu-sys-font-size-lg);
1890 }
1891
1892 .jrpg-archive-heading zen-button {
1893 flex-shrink: 0;
1894 }
1895
1896 .jrpg-archive-heading zen-button > button {
1897 border: 0;
1898 border-radius: 0;
1899 background: transparent;
1900 color: var(--mjj-jrpg-text-muted);
1901 cursor: pointer;
1902 }
1903
1904 .jrpg-archive-actions {
1905 display: flex;
1906 gap: var(--zenbu-sys-space-control);
1907 padding-block: var(--zenbu-sys-padding-sm);
1908 border-bottom: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
1909 }
1910
1911 .jrpg-archive-actions zen-button,
1912 .jrpg-archive-actions button {
1913 width: 100%;
1914 }
1915
1916 .jrpg-archive-actions button {
1917 border: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
1918 border-radius: 0;
1919 background: var(--mjj-jrpg-panel);
1920 color: var(--mjj-jrpg-primary);
1921 cursor: pointer;
1922 }
1923
1924 .jrpg-archive-actions button:hover {
1925 border-color: var(--mjj-jrpg-accent);
1926 background: var(--mjj-jrpg-surface-raised);
1927 }
1928
1929 .jrpg-archive-list {
1930 display: grid;
1931 align-content: start;
1932 gap: var(--zenbu-sys-space-icon-label);
1933 min-height: 0;
1934 margin: 0;
1935 padding: var(--zenbu-sys-padding-sm) 0;
1936 overflow-y: auto;
1937 list-style: none;
1938 scrollbar-color: var(--mjj-jrpg-frame) transparent;
1939 }
1940
1941 .jrpg-archive-list [data-conv-item] {
1942 display: grid;
1943 grid-template-columns: minmax(0, 1fr) auto;
1944 align-items: center;
1945 gap: var(--zenbu-sys-space-icon-label);
1946 padding: var(--zenbu-sys-padding-sm);
1947 border: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
1948 background: var(--mjj-jrpg-panel);
1949 }
1950
1951 .jrpg-archive-list [data-conv-open] {
1952 display: grid;
1953 gap: 0.1em;
1954 min-width: 0;
1955 border: 0;
1956 border-radius: 0;
1957 background: transparent;
1958 color: var(--mjj-jrpg-primary);
1959 cursor: pointer;
1960 text-align: left;
1961 }
1962
1963 .jrpg-archive-list [data-conv-open][aria-current="true"] {
1964 color: var(--mjj-jrpg-highlight);
1965 }
1966
1967 .jrpg-archive-list [data-conv-item]:has([data-conv-open][aria-current="true"]) {
1968 border-color: var(--mjj-jrpg-accent);
1969 background: var(--mjj-jrpg-surface-raised);
1970 }
1971
1972 .jrpg-archive-list [data-conv-item]:hover {
1973 border-color: var(--mjj-jrpg-frame);
1974 background: var(--mjj-jrpg-surface-raised);
1975 }
1976
1977 .jrpg-archive-list [data-conv-title] {
1978 overflow: hidden;
1979 white-space: nowrap;
1980 text-overflow: ellipsis;
1981 font-size: var(--zenbu-sys-font-size-sm);
1982 }
1983
1984 .jrpg-archive-list [data-conv-meta] {
1985 overflow: hidden;
1986 white-space: nowrap;
1987 text-overflow: ellipsis;
1988 color: var(--mjj-jrpg-text-muted);
1989 font-size: var(--zenbu-sys-font-size-xs);
1990 }
1991
1992 .jrpg-archive-item-actions {
1993 display: flex;
1994 gap: var(--zenbu-sys-space-icon-label);
1995 flex-shrink: 0;
1996 }
1997
1998 .jrpg-archive-item-actions button {
1999 border: 0;
2000 border-radius: 0;
2001 background: transparent;
2002 color: var(--mjj-jrpg-text-muted);
2003 cursor: pointer;
2004 font-size: var(--zenbu-sys-font-size-xs);
2005 }
2006
2007 .jrpg-archive-item-actions button:hover {
2008 color: var(--mjj-jrpg-accent);
2009 }
2010
2011 [data-archive-load-more-owner] {
2012 padding-block: var(--zenbu-sys-padding-sm);
2013 }
2014
2015 [data-archive-load-more-owner][hidden] {
2016 display: none;
2017 }
2018
2019 [data-archive-load-more-owner] > button {
2020 width: 100%;
2021 border: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
2022 border-radius: 0;
2023 background: var(--mjj-jrpg-panel);
2024 color: var(--mjj-jrpg-text-muted);
2025 cursor: pointer;
2026 }
2027
2028 [data-archive-load-more-owner] > button:hover {
2029 border-color: var(--mjj-jrpg-frame);
2030 color: var(--mjj-jrpg-primary);
2031 }
2032
2033 .jrpg-archive-status {
2034 margin: 0;
2035 padding: var(--zenbu-sys-padding-sm) 0;
2036 color: var(--mjj-jrpg-text-muted);
2037 font-size: var(--zenbu-sys-font-size-xs);
2038 }
2039
2040 .jrpg-archive-status[hidden] {
2041 display: none;
2042 }
2043
2044 .jrpg-archive-status[data-state="error"] {
2045 color: var(--mjj-jrpg-accent);
2046 }
2047
2048 .jrpg-archive-status button {
2049 border: 0;
2050 border-radius: 0;
2051 background: transparent;
2052 color: var(--mjj-jrpg-info);
2053 cursor: pointer;
2054 font-size: inherit;
2055 text-decoration: underline;
2056 }
2057
2058 /* Archive dialogs */
2059
2060 .jrpg-archive-dialog {
2061 box-sizing: border-box;
2062 min-width: min(22rem, calc(100vw - var(--zenbu-sys-space-content)));
2063 max-width: min(26rem, calc(100vw - var(--zenbu-sys-space-content)));
2064 padding: var(--zenbu-sys-padding-lg);
2065 border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
2066 border-radius: 0;
2067 background: var(--mjj-jrpg-surface-raised);
2068 color: var(--mjj-jrpg-text);
2069 box-shadow:
2070 inset 0 0 0 var(--zenbu-sys-stroke-width) var(--mjj-jrpg-accent),
2071 var(--zenbu-sys-space-control) var(--zenbu-sys-space-control) 0 var(--mjj-jrpg-accent);
2072 }
2073
2074 .jrpg-archive-dialog::backdrop {
2075 background: color-mix(in srgb, var(--mjj-jrpg-canvas) 84%, transparent);
2076 }
2077
2078 .jrpg-archive-dialog[open] {
2079 display: grid;
2080 grid-template-rows: auto auto auto;
2081 gap: var(--zenbu-sys-space-group);
2082 animation: mjj-jrpg-dialog-open var(--zenbu-sys-motion-duration-layout)
2083 var(--zenbu-sys-motion-ease-enter);
2084 }
2085
2086 .jrpg-archive-dialog-title {
2087 margin: 0;
2088 color: var(--mjj-jrpg-primary);
2089 font-size: var(--zenbu-sys-font-size-md);
2090 }
2091
2092 .jrpg-archive-dialog-subtitle {
2093 margin: 0;
2094 color: var(--mjj-jrpg-text-muted);
2095 font-size: var(--zenbu-sys-font-size-xs);
2096 overflow: hidden;
2097 white-space: nowrap;
2098 text-overflow: ellipsis;
2099 }
2100
2101 .jrpg-archive-dialog-actions {
2102 display: flex;
2103 justify-content: flex-end;
2104 gap: var(--zenbu-sys-space-control);
2105 }
2106
2107 .jrpg-archive-dialog zen-button > button {
2108 border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
2109 border-radius: 0;
2110 background: var(--mjj-jrpg-surface);
2111 color: var(--mjj-jrpg-text);
2112 cursor: pointer;
2113 }
2114
2115 .jrpg-archive-dialog zen-button > button:hover {
2116 border-color: var(--mjj-jrpg-accent);
2117 background: var(--mjj-jrpg-surface-raised);
2118 }
2119
2120 .jrpg-archive-dialog zen-field[appearance="plain"] {
2121 display: grid;
2122 gap: var(--zenbu-sys-space-icon-label);
2123 }
2124
2125 .jrpg-archive-dialog input {
2126 box-sizing: border-box;
2127 width: 100%;
2128 min-height: var(--zenbu-control-height);
2129 padding:
2130 var(--zenbu-control-padding-block)
2131 var(--zenbu-control-padding-inline);
2132 border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
2133 border-radius: 0;
2134 background: var(--mjj-jrpg-surface-sunken);
2135 color: var(--mjj-jrpg-text);
2136 font: inherit;
2137 }
2138
2139 /* Account slot — telemetry child 2 */
2140
2141 [data-frame-account] a,
2142 [data-frame-account] button,
2143 [data-frame-account] span[data-account-user] {
2144 color: var(--mjj-jrpg-primary);
2145 font-size: inherit;
2146 }
2147
2148 [data-frame-account] a {
2149 text-decoration: none;
2150 }
2151
2152 [data-frame-account] a:hover {
2153 text-decoration: underline;
2154 text-decoration-color: var(--mjj-jrpg-accent);
2155 }
2156
2157 [data-frame-account] button {
2158 border: 0;
2159 background: transparent;
2160 cursor: pointer;
2161 padding: 0;
2162 font: inherit;
2163 }
2164
2165 [data-frame-account] button:hover {
2166 color: var(--mjj-jrpg-accent);
2167 }
2168
2169 /* Quota display in composer */
2170
2171 .jrpg-composer-quota {
2172 grid-column: 1 / -1;
2173 margin: 0;
2174 color: var(--mjj-jrpg-text-muted);
2175 font-size: var(--zenbu-sys-font-size-xs);
2176 }
2177
2178 .jrpg-composer-quota[data-state="warning"] {
2179 color: var(--mjj-jrpg-highlight);
2180 }
2181
2182 .jrpg-composer-quota[data-state="exhausted"] {
2183 color: var(--mjj-jrpg-accent);
2184 }
2185
2186 .jrpg-composer-quota[hidden] {
2187 display: none;
2188 }
2189
2190 /* Archive + chat grid in mobile single-column layout */
2191
2192 @media (max-width: 34rem) {
2193 mjj-jrpg-chat,
2194 mjj-conversation-archive {
2195 grid-column: 1;
2196 grid-row: 2;
2197 }
2198 }
2199
2200
1833 @media (forced-colors: active) { 2201 @media (forced-colors: active) {
1834 .jrpg-workspace, 2202 .jrpg-workspace,
1835 .jrpg-scene, 2203 .jrpg-scene,
1836 .jrpg-scene::before { 2204 .jrpg-scene::before {
1837 background-image: none; 2205 background-image: none;
1838 } 2206 }
1839 } 2207 }
2208
2209 /* ================================================================
2210 Mobile hamburger button — hidden on desktop, used in portrait
2211 ================================================================ */
2212
2213 .jrpg-mobile-menu-btn {
2214 display: none;
2215 }
2216
2217 /* ================================================================
2218 Mobile portrait frame layout (≤52rem + portrait)
2219 Overrides the generic stacked grid from the 52rem breakpoint.
2220 All geometry custom properties are centralised in .jrpg-shell.
2221 ================================================================ */
2222
2223 @media (max-width: 52rem) and (orientation: portrait) {
2224 .jrpg-shell {
2225 /* ── Aperture geometry: (inline=left%, block=top%, width%, height%) ── */
2226
2227 /* Main conversation */
2228 --mjj-mobile-scene-inline: 4.5%;
2229 --mjj-mobile-scene-block: 7.5%;
2230 --mjj-mobile-scene-width: 91%;
2231 --mjj-mobile-scene-height: 45.5%;
2232
2233 /* Preview / utility */
2234 --mjj-mobile-utility-inline: 4.5%;
2235 --mjj-mobile-utility-block: 54.7%;
2236 --mjj-mobile-utility-width: 91%;
2237 --mjj-mobile-utility-height: 17.1%;
2238
2239 /* Composer */
2240 --mjj-mobile-composer-inline: 4.5%;
2241 --mjj-mobile-composer-block: 72.8%;
2242 --mjj-mobile-composer-width: 60.3%;
2243 --mjj-mobile-composer-height: 19.2%;
2244
2245 /* Menu */
2246 --mjj-mobile-menu-inline: 66.5%;
2247 --mjj-mobile-menu-block: 72.8%;
2248 --mjj-mobile-menu-width: 29%;
2249 --mjj-mobile-menu-height: 19.2%;
2250
2251 /* Brand / SYS-01 cover */
2252 --mjj-mobile-brand-inline: 11%;
2253 --mjj-mobile-brand-block: 2.4%;
2254 --mjj-mobile-brand-width: 10%;
2255 --mjj-mobile-brand-height: 3.5%;
2256
2257 /* Baked hamburger overlay */
2258 --mjj-mobile-hamburger-inline: 89.5%;
2259 --mjj-mobile-hamburger-block: 2%;
2260 --mjj-mobile-hamburger-width: 7%;
2261 --mjj-mobile-hamburger-height: 4%;
2262
2263 /* Telemetry value absolute positions (x = left-center, y = top-center) */
2264 --mjj-mobile-telemetry-temp-x: 22%;
2265 --mjj-mobile-telemetry-temp-y: 94.7%;
2266 --mjj-mobile-telemetry-user-x: 45%;
2267 --mjj-mobile-telemetry-user-y: 94.7%;
2268 --mjj-mobile-telemetry-status-x: 73%;
2269 --mjj-mobile-telemetry-status-y: 94.7%;
2270 --mjj-mobile-telemetry-uptime-x: 22%;
2271 --mjj-mobile-telemetry-uptime-y: 97.5%;
2272
2273 height: 100dvh;
2274 min-height: 0;
2275 }
2276
2277 .jrpg-page {
2278 overflow: hidden;
2279 }
2280
2281 .jrpg-main {
2282 height: 100dvh;
2283 min-height: 0;
2284 padding: 0;
2285 }
2286
2287 /* Workspace: switch from stacked grid back to absolute-positioned frame */
2288 .jrpg-workspace {
2289 display: block;
2290 position: relative;
2291 width: 100%;
2292 height: 100%;
2293 min-height: 0;
2294 overflow: hidden;
2295 background-image: url("/public/jrpg/background-frame-mobile.webp");
2296 background-position: top left;
2297 background-size: 100% 100%;
2298 background-repeat: no-repeat;
2299 }
2300
2301 /* Desktop window controls are irrelevant on mobile portrait */
2302 .jrpg-workspace > .jrpg-frame-controls {
2303 display: none;
2304 }
2305
2306 /* Restore absolute positioning for all aperture elements */
2307 .jrpg-workspace > .jrpg-scene,
2308 .jrpg-workspace > .jrpg-utility,
2309 .jrpg-workspace > mjj-jrpg-composer,
2310 .jrpg-workspace > mjj-jrpg-menu,
2311 .jrpg-workspace > .jrpg-brand {
2312 position: absolute;
2313 width: auto;
2314 height: auto;
2315 }
2316
2317 /* Scene aperture */
2318 .jrpg-workspace > .jrpg-scene {
2319 inset:
2320 var(--mjj-mobile-scene-block)
2321 auto
2322 auto
2323 var(--mjj-mobile-scene-inline);
2324 width: var(--mjj-mobile-scene-width);
2325 height: var(--mjj-mobile-scene-height);
2326 min-height: 0;
2327 font-size: clamp(
2328 var(--zenbu-sys-font-size-xs),
2329 2.8vw,
2330 var(--zenbu-sys-font-size-sm)
2331 );
2332 }
2333
2334 /* Utility / preview aperture */
2335 .jrpg-workspace > .jrpg-utility {
2336 inset:
2337 var(--mjj-mobile-utility-block)
2338 auto
2339 auto
2340 var(--mjj-mobile-utility-inline);
2341 width: var(--mjj-mobile-utility-width);
2342 height: var(--mjj-mobile-utility-height);
2343 min-height: 0;
2344 overflow: hidden;
2345 font-size: clamp(
2346 var(--zenbu-sys-font-size-xs),
2347 2.8vw,
2348 var(--zenbu-sys-font-size-sm)
2349 );
2350 }
2351
2352 /* Composer aperture */
2353 .jrpg-workspace > mjj-jrpg-composer {
2354 inset:
2355 var(--mjj-mobile-composer-block)
2356 auto
2357 auto
2358 var(--mjj-mobile-composer-inline);
2359 width: var(--mjj-mobile-composer-width);
2360 height: var(--mjj-mobile-composer-height);
2361 font-size: clamp(
2362 var(--zenbu-sys-font-size-xs),
2363 2.8vw,
2364 var(--zenbu-sys-font-size-sm)
2365 );
2366 }
2367
2368 /* Menu aperture */
2369 .jrpg-workspace > mjj-jrpg-menu {
2370 inset:
2371 var(--mjj-mobile-menu-block)
2372 auto
2373 auto
2374 var(--mjj-mobile-menu-inline);
2375 width: var(--mjj-mobile-menu-width);
2376 height: var(--mjj-mobile-menu-height);
2377 overflow: hidden;
2378 font-size: clamp(
2379 var(--zenbu-sys-font-size-xs),
2380 2.5vw,
2381 var(--zenbu-sys-font-size-sm)
2382 );
2383 }
2384
2385 /* Brand cover (covers baked SYS-01 label) */
2386 .jrpg-workspace > .jrpg-brand {
2387 inset:
2388 var(--mjj-mobile-brand-block)
2389 auto
2390 auto
2391 var(--mjj-mobile-brand-inline);
2392 width: var(--mjj-mobile-brand-width);
2393 height: var(--mjj-mobile-brand-height);
2394 background: var(--mjj-jrpg-canvas);
2395 padding: 0;
2396 box-shadow: none;
2397 }
2398
2399 /* Hamburger button: transparent overlay over baked art */
2400 .jrpg-workspace > .jrpg-mobile-menu-btn {
2401 display: grid;
2402 place-items: center;
2403 position: absolute;
2404 z-index: 5;
2405 inset:
2406 var(--mjj-mobile-hamburger-block)
2407 auto
2408 auto
2409 var(--mjj-mobile-hamburger-inline);
2410 width: var(--mjj-mobile-hamburger-width);
2411 height: var(--mjj-mobile-hamburger-height);
2412 }
2413
2414 .jrpg-mobile-menu-btn > button {
2415 width: 100%;
2416 height: 100%;
2417 padding: 0;
2418 border: 0;
2419 border-radius: 0;
2420 background: transparent;
2421 color: transparent;
2422 cursor: pointer;
2423 }
2424
2425 .jrpg-mobile-menu-btn zen-icon {
2426 opacity: 0;
2427 }
2428
2429 .jrpg-mobile-menu-btn > button:focus-visible {
2430 outline-color: var(--mjj-jrpg-focus);
2431 outline-style: solid;
2432 outline-width: 2px;
2433 outline-offset: 2px;
2434 color: var(--mjj-jrpg-primary);
2435 }
2436
2437 .jrpg-mobile-menu-btn > button:focus-visible zen-icon {
2438 opacity: 0.5;
2439 }
2440
2441 /* Telemetry: full-workspace container so children use workspace % coords */
2442 .jrpg-workspace > .jrpg-frame-telemetry {
2443 position: absolute;
2444 inset: 0;
2445 display: block;
2446 width: 100%;
2447 height: 100%;
2448 background: transparent;
2449 pointer-events: none;
2450 font-size: clamp(
2451 var(--zenbu-sys-font-size-xs),
2452 2.5vw,
2453 var(--zenbu-sys-font-size-sm)
2454 );
2455 }
2456
2457 .jrpg-frame-telemetry > :nth-child(1) {
2458 position: absolute;
2459 left: var(--mjj-mobile-telemetry-temp-x);
2460 top: var(--mjj-mobile-telemetry-temp-y);
2461 transform: translate(-50%, -50%);
2462 background: transparent;
2463 padding-inline: 0;
2464 pointer-events: auto;
2465 white-space: nowrap;
2466 }
2467
2468 .jrpg-frame-telemetry > :nth-child(2) {
2469 position: absolute;
2470 left: var(--mjj-mobile-telemetry-user-x);
2471 top: var(--mjj-mobile-telemetry-user-y);
2472 transform: translate(-50%, -50%);
2473 background: transparent;
2474 padding-inline: 0;
2475 pointer-events: auto;
2476 white-space: nowrap;
2477 }
2478
2479 .jrpg-frame-telemetry > :nth-child(3) {
2480 position: absolute;
2481 left: var(--mjj-mobile-telemetry-status-x);
2482 top: var(--mjj-mobile-telemetry-status-y);
2483 transform: translate(-50%, -50%);
2484 background: transparent;
2485 padding-inline: 0;
2486 pointer-events: auto;
2487 white-space: nowrap;
2488 }
2489
2490 .jrpg-frame-telemetry > :nth-child(4) {
2491 position: absolute;
2492 left: var(--mjj-mobile-telemetry-uptime-x);
2493 top: var(--mjj-mobile-telemetry-uptime-y);
2494 transform: translate(-50%, -50%);
2495 background: transparent;
2496 padding-inline: 0;
2497 pointer-events: auto;
2498 white-space: nowrap;
2499 }
2500
2501 /* Compact the brand header text for the narrow cover area */
2502 .jrpg-workspace > .jrpg-brand header h1 {
2503 font-size: clamp(
2504 var(--zenbu-sys-font-size-xs),
2505 2vw,
2506 var(--zenbu-sys-font-size-xs)
2507 );
2508 }
2509
2510 /* Compact scene internals for mobile aperture */
2511 .jrpg-scene {
2512 grid-template-columns: minmax(0, 1fr);
2513 grid-template-rows: minmax(0, 1fr);
2514 align-items: stretch;
2515 gap: var(--zenbu-sys-space-icon-label);
2516 padding: var(--zenbu-sys-padding-sm);
2517 }
2518
2519 .jrpg-scene > mjj-jrpg-character {
2520 display: none;
2521 }
2522
2523 mjj-jrpg-chat {
2524 grid-column: 1;
2525 grid-row: 1;
2526 width: 100%;
2527 height: 100%;
2528 max-height: 100%;
2529 overflow: hidden;
2530 padding: var(--zenbu-sys-padding-sm);
2531 }
2532
2533 .jrpg-utility > mjj-conversation-archive {
2534 width: 100%;
2535 height: 100%;
2536 max-height: 100%;
2537 overflow: auto;
2538 }
2539
2540 /* Utility compact padding */
2541 .jrpg-utility {
2542 padding: var(--zenbu-sys-padding-sm);
2543 }
2544
2545 /* Composer: compact single-row within aperture */
2546 .jrpg-composer {
2547 gap: var(--zenbu-sys-space-icon-label);
2548 padding: var(--zenbu-sys-padding-sm);
2549 }
2550
2551 .jrpg-composer-hint {
2552 display: none;
2553 }
2554
2555 /* Menu compact: single column stacking */
2556 .jrpg-workspace > mjj-jrpg-menu {
2557 padding: var(--zenbu-sys-padding-xs, var(--zenbu-sys-padding-sm));
2558 overflow-y: auto;
2559 scrollbar-width: thin;
2560 }
2561
2562 mjj-jrpg-menu nav {
2563 height: 100%;
2564 grid-template-columns: 1fr;
2565 }
2566
2567 mjj-jrpg-menu .jrpg-menu-label {
2568 display: none;
2569 }
2570
2571 mjj-jrpg-menu ul {
2572 grid-template-columns: minmax(0, 1fr);
2573 gap: 0;
2574 }
2575
2576 mjj-jrpg-menu button {
2577 min-height: var(--zenbu-control-height);
2578 padding-block: 0;
2579 padding-inline: var(--zenbu-control-padding-inline);
2580 font-size: var(--zenbu-sys-font-size-xs);
2581 }
2582
2583 mjj-jrpg-menu[data-mobile-menu-collapsed] {
2584 overflow: hidden;
2585 }
2586
2587 mjj-jrpg-menu[data-mobile-menu-collapsed] nav {
2588 display: grid;
2589 place-items: center;
2590 }
2591
2592 mjj-jrpg-menu[data-mobile-menu-collapsed] .jrpg-menu-label {
2593 display: block;
2594 writing-mode: initial;
2595 }
2596
2597 mjj-jrpg-menu[data-mobile-menu-collapsed] ul {
2598 display: none;
2599 }
2600
2601 /* Preview panel compact for narrow utility aperture */
2602 .jrpg-preview-panel {
2603 gap: var(--zenbu-sys-space-icon-label);
2604 padding: var(--zenbu-sys-padding-sm);
2605 overflow-y: auto;
2606 }
2607
2608 .jrpg-preview-panel h2 {
2609 font-size: var(--zenbu-sys-font-size-sm);
2610 }
2611
2612 .jrpg-preview-panel > p {
2613 font-size: var(--zenbu-sys-font-size-xs);
2614 display: -webkit-box;
2615 -webkit-line-clamp: 2;
2616 -webkit-box-orient: vertical;
2617 overflow: hidden;
2618 }
2619
2620 .jrpg-work-showcase {
2621 grid-template-columns: repeat(2, minmax(0, 1fr));
2622 gap: var(--zenbu-sys-space-icon-label);
2623 }
2624
2625 .jrpg-work-showcase a {
2626 padding: var(--zenbu-sys-padding-xs, var(--zenbu-sys-padding-sm));
2627 font-size: var(--zenbu-sys-font-size-xs);
2628 }
2629
2630 /* Archive fits within scene aperture */
2631 mjj-conversation-archive {
2632 padding: var(--zenbu-sys-padding-sm);
2633 }
2634
2635 /* Scrollable message viewport fills aperture */
2636 zen-message-scroller > .jrpg-message-viewport {
2637 scrollbar-width: thin;
2638 }
2639 }
2640
2641 /* ================================================================
2642 Login modal dialog
2643 ================================================================ */
2644
2645 .jrpg-login-dialog-owner {
2646 display: contents;
2647 }
2648
2649 .jrpg-login-dialog {
2650 box-sizing: border-box;
2651 width: min(24rem, calc(100vw - var(--zenbu-sys-space-content)));
2652 padding: var(--zenbu-sys-padding-xl);
2653 border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
2654 border-radius: 0;
2655 background: var(--mjj-jrpg-surface-raised);
2656 color: var(--mjj-jrpg-text);
2657 box-shadow:
2658 inset 0 0 0 var(--zenbu-sys-stroke-width) var(--mjj-jrpg-accent),
2659 var(--zenbu-sys-space-control) var(--zenbu-sys-space-control) 0
2660 var(--mjj-jrpg-accent);
2661 }
2662
2663 .jrpg-login-dialog::backdrop {
2664 background: color-mix(in srgb, var(--mjj-jrpg-canvas) 84%, transparent);
2665 }
2666
2667 .jrpg-login-dialog[open] {
2668 display: grid;
2669 grid-template-rows: auto auto minmax(0, 1fr);
2670 gap: var(--zenbu-sys-space-group);
2671 animation: mjj-jrpg-dialog-open var(--zenbu-sys-motion-duration-layout)
2672 var(--zenbu-sys-motion-ease-enter);
2673 }
2674
2675 .jrpg-login-dialog-header {
2676 display: flex;
2677 align-items: center;
2678 justify-content: space-between;
2679 gap: var(--zenbu-sys-space-group);
2680 padding-bottom: var(--zenbu-sys-padding-md);
2681 border-bottom: var(--zenbu-sys-stroke-width) solid var(--mjj-jrpg-frame-soft);
2682 }
2683
2684 .jrpg-login-dialog-header h2 {
2685 margin: 0;
2686 color: var(--mjj-jrpg-primary);
2687 font-size: var(--zenbu-sys-font-size-lg);
2688 letter-spacing: 0.08em;
2689 }
2690
2691 .jrpg-login-dialog-header zen-button > button {
2692 width: var(--zenbu-control-height);
2693 padding: 0;
2694 border: 0;
2695 border-radius: 0;
2696 background: transparent;
2697 color: var(--mjj-jrpg-text-muted);
2698 cursor: pointer;
2699 }
2700
2701 .jrpg-login-dialog [data-login-error] {
2702 padding: var(--zenbu-sys-padding-sm);
2703 border-left: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-accent);
2704 background: color-mix(in srgb, var(--mjj-jrpg-accent) 10%, transparent);
2705 color: var(--mjj-jrpg-accent);
2706 font-size: var(--zenbu-sys-font-size-sm);
2707 }
2708
2709 .jrpg-login-dialog [data-login-error][hidden] {
2710 display: none;
2711 }
2712
2713 .jrpg-login-dialog form {
2714 display: grid;
2715 gap: var(--zenbu-sys-space-group);
2716 }
2717
2718 .jrpg-login-dialog zen-field[appearance="plain"] {
2719 display: grid;
2720 gap: var(--zenbu-sys-space-icon-label);
2721 }
2722
2723 .jrpg-login-dialog input {
2724 box-sizing: border-box;
2725 width: 100%;
2726 min-height: var(--zenbu-control-height);
2727 padding:
2728 var(--zenbu-control-padding-block)
2729 var(--zenbu-control-padding-inline);
2730 border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
2731 border-radius: 0;
2732 background: var(--mjj-jrpg-surface-sunken);
2733 color: var(--mjj-jrpg-text);
2734 font: inherit;
2735 }
2736
2737 .jrpg-login-dialog input::placeholder {
2738 color: var(--mjj-jrpg-text-muted);
2739 }
2740
2741 .jrpg-login-dialog-actions {
2742 display: flex;
2743 justify-content: flex-end;
2744 gap: var(--zenbu-sys-space-control);
2745 }
2746
2747 .jrpg-login-dialog zen-button > button {
2748 border: var(--zenbu-sys-stroke-width-emphasis) solid var(--mjj-jrpg-frame);
2749 border-radius: 0;
2750 background: var(--mjj-jrpg-surface);
2751 color: var(--mjj-jrpg-text);
2752 cursor: pointer;
2753 }
2754
2755 .jrpg-login-dialog zen-button > button:hover {
2756 border-color: var(--mjj-jrpg-accent);
2757 background: var(--mjj-jrpg-surface-raised);
2758 }
2759
2760 .jrpg-login-dialog [data-login-submit] {
2761 border-color: var(--mjj-jrpg-primary);
2762 background: var(--mjj-jrpg-primary);
2763 color: var(--mjj-jrpg-primary-foreground);
2764 }
2765
2766 .jrpg-login-dialog [data-login-submit]:hover {
2767 border-color: var(--mjj-jrpg-primary-hover);
2768 background: var(--mjj-jrpg-primary-hover);
2769 }
2770
2771 .jrpg-login-dialog zen-button > button:disabled {
2772 opacity: var(--zenbu-sys-opacity-disabled);
2773 cursor: not-allowed;
2774 }
2775
2776 @media (prefers-reduced-motion: reduce) {
2777 .jrpg-login-dialog[open] {
2778 animation: none;
2779 }
2780 }