Index: trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 6895)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/LineElemStyle.java	(revision 6896)
@@ -184,5 +184,5 @@
         }
 
-        int alpha = 255;
+        int alpha = color.getAlpha();
         Integer pAlpha = Utils.color_float2int(c.get(type.prefix + OPACITY, null, Float.class));
         if (pAlpha != null) {
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java	(revision 6895)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/StyleSource.java	(revision 6896)
@@ -21,4 +21,10 @@
 import org.openstreetmap.josm.tools.Utils;
 
+/**
+ * A mappaint style (abstract class).
+ *
+ * Handles everything from parsing the style definition to application
+ * of the style to an osm primitive.
+ */
 public abstract class StyleSource extends SourceEntry {
 
@@ -44,4 +50,20 @@
     }
 
+    /**
+     * Apply style to osm primitive.
+     *
+     * Adds properties to a MultiCascade. All active {@link StyleSource}s add
+     * their properties on after the other. At a later stage, concrete painting
+     * primitives (lines, icons, text, ...) are derived from the MultiCascade.
+     * @param mc the current MultiCascade, empty for the first StyleSource
+     * @param osm the primitive
+     * @param scale the map scale
+     * @param multipolyOuterWay support for a very old multipolygon tagging style
+     * where you add the tags both to the outer and the inner way.
+     * However, independent inner way style is also possible.
+     * @param pretendWayIsClosed For styles that require the way to be closed,
+     * we pretend it is. This is useful for generating area styles from the (segmented)
+     * outer ways of a multipolygon.
+     */
     public abstract void apply(MultiCascade mc, OsmPrimitive osm, double scale, OsmPrimitive multipolyOuterWay, boolean pretendWayIsClosed);
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 6895)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java	(revision 6896)
@@ -731,4 +731,18 @@
             return result;
         }
+
+        @Override
+        public String toString() {
+            StringBuilder b = new StringBuilder("ParameterFunction~");
+            b.append(m.getName()).append("(");
+            for (int i = 0; i < args.size(); ++i) {
+                if (i > 0) b.append(",");
+                b.append(expectedParameterTypes[i]);
+                b.append(" ").append(args.get(i));
+            }
+            b.append(')');
+            return b.toString();
+        }
+
     }
 
@@ -780,4 +794,17 @@
             return result;
         }
+        @Override
+        public String toString() {
+            StringBuilder b = new StringBuilder("ArrayFunction~");
+            b.append(m.getName()).append("(");
+            for (int i = 0; i < args.size(); ++i) {
+                if (i > 0) b.append(",");
+                b.append(arrayComponentType);
+                b.append(" ").append(args.get(i));
+            }
+            b.append(')');
+            return b.toString();
+        }
+
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 6895)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java	(revision 6896)
@@ -85,5 +85,5 @@
         @Override
         public String toString() {
-            return key + ':' + (val instanceof float[] ? Arrays.toString((float[]) val) : val) + ';';
+            return key + ": " + (val instanceof float[] ? Arrays.toString((float[]) val) : val instanceof String ? "String<"+val+">" : val) + ';';
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 6895)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 6896)
@@ -41,8 +41,20 @@
 
 <DEFAULT>
+TOKEN [IGNORE_CASE]:
+{
+ /* Special keywords in some contexts, ordinary identifiers in other contexts.
+    Don't use the javacc token contexts (except DEFAULT and COMMENT) because
+    they complicate error handling. Instead simply add a parsing rule <code>ident()</code>
+    that parses the IDENT token and in addition all the keyword tokens. */
+    < AND: "and" >
+|   < SET: "set" >
+|   < NOT: "not" >
+|   < MEDIA: "@media" >
+}
+
+<DEFAULT>
 TOKEN:
 {
-    < SET: ("set" | "SET") >
-|   < IDENT: ["a"-"z","A"-"Z","_"] ( ["a"-"z","A"-"Z","_","-","0"-"9"] )* >
+    < IDENT: ["a"-"z","A"-"Z","_"] ( ["a"-"z","A"-"Z","_","-","0"-"9"] )* >
 |   < UINT: ["1"-"9"] ( ["0"-"9"] )* >
 |   < UFLOAT: ( ["0"-"9"] )+ ( "." ( ["0"-"9"] )+ )? >
@@ -122,4 +134,13 @@
  * 'val' can be a literal, or an expression like "prop(width, default) + 0.8".
  *
+ * @media { ... } queries are supported, following http://www.w3.org/TR/css3-mediaqueries/#syntax
+ *
+ *                               media_query
+ *         ___________________________|_______________________________
+ *        |                                                           |
+ * @media all and (min-josm-version: 7789) and (max-josm-version: 7790), all and (user-agent: xyz) { ... }
+ *                |______________________|
+ *                          |
+ *                    media_expression
  */
 
@@ -166,4 +187,13 @@
 }
 
+String ident():
+{
+    Token t;
+    String s;
+}
+{
+    ( t=<IDENT> | t=<SET> | t=<NOT> | t=<AND> ) { return t.image; }
+}
+
 String string_or_ident() :
 {
@@ -172,5 +202,5 @@
 }
 {
-    t=<IDENT> { return t.image; } | s=string() { return s; }
+    ( s=ident() | s=string() ) { return s; }
 }
 
@@ -229,12 +259,72 @@
 {
     MapCSSRule r;
-    Token com = null;
 }
 {
     { this.sheet = sheet; }
     w()
+    rules(true) ( media() w() rules(true) )*
+    <EOF>
+}
+
+void media():
+{
+    boolean pass = false;
+    boolean q;
+    boolean empty = true;
+}
+{
+    <MEDIA> w()
+    ( q=media_query() { pass = pass || q; empty = false; }
+        ( <COMMA> w() q=media_query() { pass = pass || q; } )*
+    )?
+    <LBRACE> w()
+    rules(empty || pass)
+    <RBRACE>
+}
+
+boolean media_query():
+{
+    Token t;
+    String mediatype = "all";
+    boolean pass = true;
+    boolean invert = false;
+    boolean e;
+}
+{
+    ( <NOT> { invert = true; } w() )?
+    (
+            t=<IDENT> { mediatype = t.image.toLowerCase(); } w()
+            ( <AND> w() e=media_expression() { pass = pass && e; } w() )*
+        |
+            e=media_expression() { pass = pass && e; } w()
+            ( <AND> w() e=media_expression() { pass = pass && e; } w() )*
+    )
+    { 
+        if (!"all".equals(mediatype)) {
+            pass = false;
+        }
+        return invert ? (!pass) : pass;
+    }
+}
+
+boolean media_expression():
+{
+    Token t;
+    String feature;
+    Object val = null;
+}
+{
+    <LPAR> w() t=<IDENT> { feature = t.image; } w() ( <COLON> w() val=literal() )? <RPAR>
+    { return this.sheet.evalMediaExpression(feature, val); }
+}
+
+void rules(boolean add):
+{
+    MapCSSRule r;
+}
+{
     (
         try {
-                r=rule() { if (r != null) { sheet.rules.add(r); } } w()
+            r=rule() { if (add && r != null) { sheet.rules.add(r); } } w()
         } catch (MapCSSException mex) {
             error_skipto(RBRACE, mex);
@@ -245,5 +335,4 @@
         }
     )*
-    <EOF>
 }
 
@@ -345,5 +434,5 @@
 String tag_key() :
 {
-    String s;
+    String s, s2;
     Token t;
 }
@@ -351,5 +440,5 @@
         s=string() { return s; }
     |
-        t=<IDENT> { s = t.image; } ( <COLON> t=<IDENT> { s += ':' + t.image; } )* { return s; }
+        s=ident() ( <COLON> s2=ident() { s += ':' + s2; } )* { return s; }
 }
 
@@ -435,5 +524,5 @@
 Condition class_or_pseudoclass(Context context) :
 {
-    Token t;
+    String s;
     boolean not = false;
     boolean pseudo;
@@ -446,18 +535,17 @@
         <COLON> { pseudo = true; }
     )
-    t=<IDENT>
+    s=ident()
     { return pseudo
-        ? Condition.createPseudoClassCondition(t.image, not, context)
-        : Condition.createClassCondition(t.image, not, context); }
+        ? Condition.createPseudoClassCondition(s, not, context)
+        : Condition.createClassCondition(s, not, context); }
 }
 
 String subpart() :
 {
-    Token t;
+    String s;
 }
 {
     <DCOLON>
-    ( t=<IDENT> | t=<STAR> )
-    { return t.image; }
+    ( s=ident() { return s; } | <STAR> { return "*"; } )
 }
 
@@ -573,5 +661,5 @@
 }
 {
-    tmp=<IDENT> { name = tmp.image; } w()
+    name=ident() w()
     <LPAR> w()
     (
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 6895)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java	(revision 6896)
@@ -16,4 +16,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -213,4 +214,20 @@
     }
 
+    public boolean evalMediaExpression(String feature, Object val) {
+        if ("user-agent".equals(feature)) {
+            String s = Cascade.convertTo(val, String.class);
+            if ("josm".equals(s)) return true;
+        }
+        if ("min-josm-version".equals(feature)) {
+            Float v = Cascade.convertTo(val, Float.class);
+            if (v != null) return Math.round(v) <= Version.getInstance().getVersion();
+        }
+        if ("max-josm-version".equals(feature)) {
+            Float v = Cascade.convertTo(val, Float.class);
+            if (v != null) return Math.round(v) >= Version.getInstance().getVersion();
+        }
+        return false;
+    }
+
     @Override
     public String toString() {
